mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 10:47:18 +00:00 
			
		
		
		
	move slinfactory structure definition back to header... it's just easier to use this way
add infrastructure for whispering onto a channel git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@38422 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		
							
								
								
									
										86
									
								
								channel.c
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								channel.c
									
									
									
									
									
								
							| @@ -66,6 +66,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | ||||
| #include "asterisk/transcap.h" | ||||
| #include "asterisk/devicestate.h" | ||||
| #include "asterisk/sha1.h" | ||||
| #include "asterisk/slinfactory.h" | ||||
|  | ||||
| struct channel_spy_trans { | ||||
| 	int last_format; | ||||
| @@ -78,6 +79,12 @@ struct ast_channel_spy_list { | ||||
| 	AST_LIST_HEAD_NOLOCK(, ast_channel_spy) list; | ||||
| }; | ||||
|  | ||||
| struct ast_channel_whisper_buffer { | ||||
| 	ast_mutex_t lock; | ||||
| 	struct ast_slinfactory sf; | ||||
| 	unsigned int original_format; | ||||
| }; | ||||
|  | ||||
| /* uncomment if you have problems with 'monitoring' synchronized files */ | ||||
| #if 0 | ||||
| #define MONITOR_CONSTANT_DELAY | ||||
| @@ -987,14 +994,17 @@ void ast_channel_free(struct ast_channel *chan) | ||||
| 	ast_copy_string(name, chan->name, sizeof(name)); | ||||
|  | ||||
| 	/* Stop monitoring */ | ||||
| 	if (chan->monitor) { | ||||
| 	if (chan->monitor) | ||||
| 		chan->monitor->stop( chan, 0 ); | ||||
| 	} | ||||
|  | ||||
| 	/* If there is native format music-on-hold state, free it */ | ||||
| 	if(chan->music_state) | ||||
| 	if (chan->music_state) | ||||
| 		ast_moh_cleanup(chan); | ||||
|  | ||||
| 	/* if someone is whispering on the channel, stop them */ | ||||
| 	if (chan->whisper) | ||||
| 		ast_channel_whisper_stop(chan); | ||||
|  | ||||
| 	/* Free translators */ | ||||
| 	if (chan->readtrans) | ||||
| 		ast_translator_free_path(chan->readtrans); | ||||
| @@ -2445,6 +2455,25 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if (ast_test_flag(chan, AST_FLAG_WHISPER)) { | ||||
| 				/* frame is assumed to be in SLINEAR, since that is | ||||
| 				   required for whisper mode */ | ||||
| 				ast_frame_adjust_volume(f, -2); | ||||
| 				if (ast_slinfactory_available(&chan->whisper->sf) >= f->samples) { | ||||
| 					short buf[f->samples]; | ||||
| 					struct ast_frame whisper = { | ||||
| 						.frametype = AST_FRAME_VOICE, | ||||
| 						.subclass = AST_FORMAT_SLINEAR, | ||||
| 						.data = buf, | ||||
| 						.datalen = sizeof(buf), | ||||
| 						.samples = f->samples, | ||||
| 					}; | ||||
|  | ||||
| 					if (ast_slinfactory_read(&chan->whisper->sf, buf, f->samples)) | ||||
| 						ast_frame_slinear_sum(f, &whisper); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			res = chan->tech->write(chan, f); | ||||
| 		} | ||||
| 		break;	 | ||||
| @@ -3171,6 +3200,16 @@ int ast_do_masquerade(struct ast_channel *original) | ||||
| 		if (x != AST_GENERATOR_FD) | ||||
| 			original->fds[x] = clone->fds[x]; | ||||
| 	} | ||||
|  | ||||
| 	/* move any whisperer over */ | ||||
| 	ast_channel_whisper_stop(original); | ||||
| 	if (ast_test_flag(clone, AST_FLAG_WHISPER)) { | ||||
| 		original->whisper = clone->whisper; | ||||
| 		ast_set_flag(original, AST_FLAG_WHISPER); | ||||
| 		clone->whisper = NULL; | ||||
| 		ast_clear_flag(clone, AST_FLAG_WHISPER); | ||||
| 	} | ||||
|  | ||||
| 	/* Move data stores over */ | ||||
| 	if (AST_LIST_FIRST(&clone->datastores)) | ||||
|                 AST_LIST_INSERT_TAIL(&original->datastores, AST_LIST_FIRST(&clone->datastores), entry); | ||||
| @@ -4401,4 +4440,43 @@ int ast_say_digits_full(struct ast_channel *chan, int num, | ||||
|         return ast_say_digit_str_full(chan, buf, ints, lang, audiofd, ctrlfd); | ||||
| } | ||||
|  | ||||
| /* end of file */ | ||||
| int ast_channel_whisper_start(struct ast_channel *chan) | ||||
| { | ||||
| 	if (chan->whisper) | ||||
| 		return -1; | ||||
|  | ||||
| 	if (!(chan->whisper = ast_calloc(1, sizeof(*chan->whisper)))) | ||||
| 		return -1; | ||||
|  | ||||
| 	ast_mutex_init(&chan->whisper->lock); | ||||
| 	ast_slinfactory_init(&chan->whisper->sf); | ||||
| 	chan->whisper->original_format = ast_set_write_format(chan, AST_FORMAT_SLINEAR); | ||||
| 	ast_set_flag(chan, AST_FLAG_WHISPER); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int ast_channel_whisper_feed(struct ast_channel *chan, struct ast_frame *f) | ||||
| { | ||||
| 	if (!chan->whisper) | ||||
| 		return -1; | ||||
|  | ||||
| 	ast_mutex_lock(&chan->whisper->lock); | ||||
| 	ast_slinfactory_feed(&chan->whisper->sf, f); | ||||
| 	ast_mutex_unlock(&chan->whisper->lock); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void ast_channel_whisper_stop(struct ast_channel *chan) | ||||
| { | ||||
| 	if (!chan->whisper) | ||||
| 		return; | ||||
|  | ||||
| 	ast_clear_flag(chan, AST_FLAG_WHISPER); | ||||
| 	ast_set_write_format(chan, chan->whisper->original_format); | ||||
| 	ast_slinfactory_destroy(&chan->whisper->sf); | ||||
| 	ast_mutex_destroy(&chan->whisper->lock); | ||||
| 	free(chan->whisper); | ||||
| 	chan->whisper = NULL; | ||||
| } | ||||
|   | ||||
							
								
								
									
										2
									
								
								frame.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								frame.c
									
									
									
									
									
								
							| @@ -359,7 +359,7 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr) | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| struct ast_frame *ast_frdup(struct ast_frame *f) | ||||
| struct ast_frame *ast_frdup(const struct ast_frame *f) | ||||
| { | ||||
| 	struct ast_frame *out; | ||||
| 	int len, srclen = 0; | ||||
|   | ||||
| @@ -268,6 +268,7 @@ struct ast_channel_tech { | ||||
| }; | ||||
|  | ||||
| struct ast_channel_spy_list; | ||||
| struct ast_channel_whisper_buffer; | ||||
|  | ||||
| #define	DEBUGCHAN_FLAG  0x80000000 | ||||
| #define	FRAMECOUNT_INC(x)	( ((x) & DEBUGCHAN_FLAG) | ((x++) & ~DEBUGCHAN_FLAG) ) | ||||
| @@ -382,6 +383,7 @@ struct ast_channel { | ||||
| 	int rawwriteformat;				/*!< Raw write format */ | ||||
|  | ||||
| 	struct ast_channel_spy_list *spies;		/*!< Chan Spy stuff */ | ||||
| 	struct ast_channel_whisper_buffer *whisper;	/*!< Whisper Paging buffer */ | ||||
| 	AST_LIST_ENTRY(ast_channel) chan_list;		/*!< For easy linking */ | ||||
| 	struct ast_jb jb;				/*!< The jitterbuffer state  */ | ||||
|  | ||||
| @@ -397,21 +399,20 @@ struct ast_channel { | ||||
| /*! \brief Channels have this property if they can create jitter; i.e. most VoIP channels */ | ||||
| #define AST_CHAN_TP_CREATESJITTER (1 << 1) | ||||
|  | ||||
| /* This flag has been deprecated by the transfercapbilty data member in struct ast_channel */ | ||||
| /* #define AST_FLAG_DIGITAL	(1 << 0) */	/* if the call is a digital ISDN call */ | ||||
| #define AST_FLAG_DEFER_DTMF	(1 << 1)	/*!< if dtmf should be deferred */ | ||||
| #define AST_FLAG_WRITE_INT	(1 << 2)	/*!< if write should be interrupt generator */ | ||||
| #define AST_FLAG_BLOCKING	(1 << 3)	/*!< if we are blocking */ | ||||
| #define AST_FLAG_ZOMBIE		(1 << 4)	/*!< if we are a zombie */ | ||||
| #define AST_FLAG_EXCEPTION	(1 << 5)	/*!< if there is a pending exception */ | ||||
| #define AST_FLAG_MOH		(1 << 6)	/*!< XXX anthm promises me this will disappear XXX listening to moh */ | ||||
| #define AST_FLAG_SPYING		(1 << 7)	/*!< XXX might also go away XXX is spying on someone */ | ||||
| #define AST_FLAG_SPYING		(1 << 7)	/*!< is spying on someone */ | ||||
| #define AST_FLAG_NBRIDGE	(1 << 8)	/*!< is it in a native bridge */ | ||||
| #define AST_FLAG_IN_AUTOLOOP	(1 << 9)	/*!< the channel is in an auto-incrementing dialplan processor, | ||||
| 						   so when ->priority is set, it will get incremented before | ||||
| 						   finding the next priority to run | ||||
| 						*/ | ||||
| #define AST_FLAG_OUTGOING (1 << 10) /*! Is this call outgoing */ | ||||
| 						   finding the next priority to run */ | ||||
| #define AST_FLAG_OUTGOING	(1 << 10)	/*!< Is this call outgoing */ | ||||
| #define AST_FLAG_WHISPER	(1 << 11)	/*!< Is this channel being whispered on */ | ||||
|  | ||||
| /* @} */ | ||||
|  | ||||
| #define AST_FEATURE_PLAY_WARNING	(1 << 0) | ||||
| @@ -1277,6 +1278,38 @@ const char *channelreloadreason2txt(enum channelreloadreason reason); | ||||
| /*! \brief return an ast_variable list of channeltypes */ | ||||
| struct ast_variable *ast_channeltype_list(void); | ||||
|  | ||||
| /*! | ||||
|   \brief Begin 'whispering' onto a channel | ||||
|   \param chan The channel to whisper onto | ||||
|   \return 0 for success, non-zero for failure | ||||
|  | ||||
|   This function will add a whisper buffer onto a channel and set a flag | ||||
|   causing writes to the channel to reduce the volume level of the written | ||||
|   audio samples, and then to mix in audio from the whisper buffer if it | ||||
|   is available. | ||||
|  | ||||
|   Note: This function performs no locking; you must hold the channel's lock before | ||||
|   calling this function. | ||||
|  */ | ||||
| int ast_channel_whisper_start(struct ast_channel *chan); | ||||
|  | ||||
| /*! | ||||
|   \brief Feed an audio frame into the whisper buffer on a channel | ||||
|   \param chan The channel to whisper onto | ||||
|   \return 0 for success, non-zero for failure | ||||
|  */ | ||||
| int ast_channel_whisper_feed(struct ast_channel *chan, struct ast_frame *f); | ||||
|  | ||||
| /*! | ||||
|   \brief Stop 'whispering' onto a channel | ||||
|   \param chan The channel to whisper onto | ||||
|   \return 0 for success, non-zero for failure | ||||
|  | ||||
|   Note: This function performs no locking; you must hold the channel's lock before | ||||
|   calling this function. | ||||
|  */ | ||||
| void ast_channel_whisper_stop(struct ast_channel *chan); | ||||
|  | ||||
| #if defined(__cplusplus) || defined(c_plusplus) | ||||
| } | ||||
| #endif | ||||
|   | ||||
| @@ -354,7 +354,7 @@ struct ast_frame *ast_fralloc(char *source, int len); | ||||
|  */ | ||||
| void ast_frfree(struct ast_frame *fr); | ||||
|  | ||||
| /*! \brief Copies a frame  | ||||
| /*! \brief Makes a frame independent of any static storage | ||||
|  * \param fr frame to act upon | ||||
|  * Take a frame, and if it's not been malloc'd, make a malloc'd copy | ||||
|  * and if the data hasn't been malloced then make the | ||||
| @@ -366,10 +366,10 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr); | ||||
|  | ||||
| /*! \brief Copies a frame  | ||||
|  * \param fr frame to copy | ||||
|  * Dupliates a frame -- should only rarely be used, typically frisolate is good enough | ||||
|  * Duplicates a frame -- should only rarely be used, typically frisolate is good enough | ||||
|  * \return Returns a frame on success, NULL on error | ||||
|  */ | ||||
| struct ast_frame *ast_frdup(struct ast_frame *fr); | ||||
| struct ast_frame *ast_frdup(const struct ast_frame *fr); | ||||
|  | ||||
| /*! \brief Reads a frame from an fd | ||||
|  * Read a frame from a stream or packet fd, as written by fd_write | ||||
|   | ||||
| @@ -31,7 +31,15 @@ | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| struct ast_slinfactory; | ||||
| struct ast_slinfactory { | ||||
| 	struct ast_frame *queue; | ||||
| 	struct ast_trans_pvt *trans; | ||||
| 	short hold[1280]; | ||||
| 	short *offset; | ||||
| 	size_t holdlen;			/*!< in samples */ | ||||
| 	unsigned int size;		/*!< in samples */ | ||||
| 	unsigned int format; | ||||
| }; | ||||
|  | ||||
| void ast_slinfactory_init(struct ast_slinfactory *sf); | ||||
| void ast_slinfactory_destroy(struct ast_slinfactory *sf); | ||||
|   | ||||
| @@ -35,16 +35,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | ||||
| #include "asterisk/logger.h" | ||||
| #include "asterisk/translate.h" | ||||
|  | ||||
| struct ast_slinfactory { | ||||
| 	struct ast_frame *queue; | ||||
| 	struct ast_trans_pvt *trans; | ||||
| 	short hold[1280]; | ||||
| 	short *offset; | ||||
| 	size_t holdlen;			/*! in samples */ | ||||
| 	unsigned int size;		/*! in samples */ | ||||
| 	unsigned int format; | ||||
| }; | ||||
|  | ||||
| void ast_slinfactory_init(struct ast_slinfactory *sf)  | ||||
| { | ||||
| 	memset(sf, 0, sizeof(*sf)); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user