Skip to content
Snippets Groups Projects
channel.c 115 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	} else {
    		if (need_dup) {
    			result = ast_frdup(read_frame);
    			result->next = ast_frdup(write_frame);
    		} else {
    			result = read_frame;
    			result->next = write_frame;
    		}
    	}
    
    	return result;
    }
    
    
    static void *silence_generator_alloc(struct ast_channel *chan, void *data)
    {
    	/* just store the data pointer in the channel structure */
    	return data;
    }
    
    static void silence_generator_release(struct ast_channel *chan, void *data)
    {
    	/* nothing to do */
    }
    
    static int silence_generator_generate(struct ast_channel *chan, void *data, int len, int samples) 
    {
    	if (samples == 160) {
    
    		short buf[160] = { 0, };
    		struct ast_frame frame = {
    			.frametype = AST_FRAME_VOICE,
    			.subclass = AST_FORMAT_SLINEAR,
    			.data = buf,
    			.samples = 160,
    			.datalen = sizeof(buf),
    		};
    
    		if (ast_write(chan, &frame))
    
    			return -1;
    	} else {
    		short buf[samples];
    		int x;
    		struct ast_frame frame = {
    			.frametype = AST_FRAME_VOICE,
    			.subclass = AST_FORMAT_SLINEAR,
    
    			.samples = samples,
    			.datalen = sizeof(buf),
    		};
    
    		for (x = 0; x < samples; x++)
    			buf[x] = 0;
    
    		if (ast_write(chan, &frame))
    			return -1;
    	}
    
    	return 0;
    }
    
    static struct ast_generator silence_generator = {
    	.alloc = silence_generator_alloc,
    	.release = silence_generator_release,
    	.generate = silence_generator_generate, 
    };
    
    struct ast_silence_generator {
    	int old_write_format;
    };
    
    struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_channel *chan)
    {
    	struct ast_silence_generator *state;
    
    	if (!(state = calloc(1, sizeof(*state)))) {
    		ast_log(LOG_WARNING, "Could not allocate state structure\n");
    		return NULL;
    	}
    
    	state->old_write_format = chan->writeformat;
    
    	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
    		ast_log(LOG_ERROR, "Could not set write format to SLINEAR\n");
    		free(state);
    		return NULL;
    	}
    
    	ast_activate_generator(chan, &silence_generator, state);
    
    	if (option_debug)
    		ast_log(LOG_DEBUG, "Started silence generator on '%s'\n", chan->name);
    
    	return state;
    }
    
    void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
    {
    	if (!state)
    		return;
    
    	ast_deactivate_generator(chan);
    
    	if (option_debug)
    		ast_log(LOG_DEBUG, "Stopped silence generator on '%s'\n", chan->name);
    
    	if (ast_set_write_format(chan, state->old_write_format) < 0)
    		ast_log(LOG_ERROR, "Could not return write format to its original state\n");
    
    	free(state);
    }
    
    
    
    /*! \ brief Convert channel reloadreason (ENUM) to text string for manager event */
    const char *channelreloadreason2txt(enum channelreloadreason reason) {
    	switch (reason) {
    	case CHANNEL_MODULE_LOAD:	return "LOAD (Channel module load)";
    					break;
    	case CHANNEL_MODULE_RELOAD:	return "RELOAD (Channel module reload)";
    					break;
    	case CHANNEL_CLI_RELOAD:	return "CLIRELOAD (Channel module reload by CLI command)";
    					break;
    	default:	return "MANAGERRELOAD (Channel module reload by manager)";
    					break;
    	}
    };