@@ -22,8 +22,8 @@ class Microphone: # pylint: disable=too-many-instance-attributes
2222
2323 _logger : verboselogs .VerboseLogger
2424
25- _audio : "pyaudio.PyAudio"
26- _stream : "pyaudio.Stream"
25+ _audio : Optional [ "pyaudio.PyAudio" ] = None
26+ _stream : Optional [ "pyaudio.Stream" ] = None
2727
2828 _chunk : int
2929 _rate : int
@@ -145,77 +145,49 @@ def start(self) -> bool:
145145 self ._asyncio_thread = None
146146 self ._push_callback = self ._push_callback_org
147147
148- self ._stream = self ._audio .open (
149- format = self ._format ,
150- channels = self ._channels ,
151- rate = self ._rate ,
152- input = True ,
153- frames_per_buffer = self ._chunk ,
154- input_device_index = self ._input_device_index ,
155- stream_callback = self ._callback ,
156- )
148+ if self ._audio is not None :
149+ self ._stream = self ._audio .open (
150+ format = self ._format ,
151+ channels = self ._channels ,
152+ rate = self ._rate ,
153+ input = True ,
154+ output = False ,
155+ frames_per_buffer = self ._chunk ,
156+ input_device_index = self ._input_device_index ,
157+ stream_callback = self ._callback ,
158+ )
159+
160+ if self ._stream is None :
161+ self ._logger .error ("start failed. No stream created." )
162+ self ._logger .debug ("Microphone.start LEAVE" )
163+ return False
157164
158165 self ._exit .clear ()
159- self ._stream .start_stream ()
166+ if self ._stream is not None :
167+ self ._stream .start_stream ()
160168
161169 self ._logger .notice ("start succeeded" )
162170 self ._logger .debug ("Microphone.start LEAVE" )
163171 return True
164172
165- def _callback (
166- self , input_data , frame_count , time_info , status_flags
167- ): # pylint: disable=unused-argument
168- """
169- The callback used to process data in callback mode.
170- """
171- # dynamic import of pyaudio as not to force the requirements on the SDK (and users)
172- import pyaudio # pylint: disable=import-outside-toplevel
173-
174- self ._logger .debug ("Microphone._callback ENTER" )
175-
176- if self ._exit .is_set ():
177- self ._logger .info ("exit is Set" )
178- self ._logger .notice ("_callback stopping..." )
179- self ._logger .debug ("Microphone._callback LEAVE" )
180- return None , pyaudio .paAbort
181-
182- if input_data is None :
183- self ._logger .warning ("input_data is None" )
184- self ._logger .debug ("Microphone._callback LEAVE" )
185- return None , pyaudio .paContinue
186-
187- try :
188- if self ._is_muted :
189- size = len (input_data )
190- input_data = b"\x00 " * size
191-
192- self ._push_callback (input_data )
193- except Exception as e :
194- self ._logger .error ("Error while sending: %s" , str (e ))
195- self ._logger .debug ("Microphone._callback LEAVE" )
196- raise
197-
198- self ._logger .debug ("Microphone._callback LEAVE" )
199- return input_data , pyaudio .paContinue
200-
201173 def mute (self ) -> bool :
202174 """
203175 mute - mutes the microphone stream
204176
205177 Returns:
206178 bool: True if the stream was muted, False otherwise
207179 """
208- self ._logger .debug ("Microphone.mute ENTER" )
180+ self ._logger .verbose ("Microphone.mute ENTER" )
209181
210182 if self ._stream is None :
211183 self ._logger .error ("mute failed. Library not initialized." )
212- self ._logger .debug ("Microphone.mute LEAVE" )
184+ self ._logger .verbose ("Microphone.mute LEAVE" )
213185 return False
214186
215187 self ._is_muted = True
216188
217189 self ._logger .notice ("mute succeeded" )
218- self ._logger .debug ("Microphone.mute LEAVE" )
190+ self ._logger .verbose ("Microphone.mute LEAVE" )
219191 return True
220192
221193 def unmute (self ) -> bool :
@@ -225,19 +197,42 @@ def unmute(self) -> bool:
225197 Returns:
226198 bool: True if the stream was unmuted, False otherwise
227199 """
228- self ._logger .debug ("Microphone.unmute ENTER" )
200+ self ._logger .verbose ("Microphone.unmute ENTER" )
229201
230202 if self ._stream is None :
231203 self ._logger .error ("unmute failed. Library not initialized." )
232- self ._logger .debug ("Microphone.unmute LEAVE" )
204+ self ._logger .verbose ("Microphone.unmute LEAVE" )
233205 return False
234206
235207 self ._is_muted = False
236208
237209 self ._logger .notice ("unmute succeeded" )
238- self ._logger .debug ("Microphone.unmute LEAVE" )
210+ self ._logger .verbose ("Microphone.unmute LEAVE" )
239211 return True
240212
213+ def is_muted (self ) -> bool :
214+ """
215+ is_muted - returns the state of the stream
216+
217+ Args:
218+ None
219+
220+ Returns:
221+ True if the stream is muted, False otherwise
222+ """
223+ self ._logger .spam ("Microphone.is_muted ENTER" )
224+
225+ if self ._stream is None :
226+ self ._logger .spam ("is_muted: stream is None" )
227+ self ._logger .spam ("Microphone.is_muted LEAVE" )
228+ return False
229+
230+ val = self ._is_muted
231+
232+ self ._logger .spam ("is_muted: %s" , val )
233+ self ._logger .spam ("Microphone.is_muted LEAVE" )
234+ return val
235+
241236 def finish (self ) -> bool :
242237 """
243238 finish - stops the microphone stream
@@ -255,7 +250,6 @@ def finish(self) -> bool:
255250 self ._logger .notice ("stopping stream..." )
256251 self ._stream .stop_stream ()
257252 self ._stream .close ()
258- self ._stream = None # type: ignore
259253 self ._logger .notice ("stream stopped" )
260254
261255 # clean up the thread
@@ -265,13 +259,43 @@ def finish(self) -> bool:
265259 self ._asyncio_thread
266260 is not None
267261 ):
268- self ._logger .notice ("stopping asyncio loop ..." )
262+ self ._logger .notice ("stopping _asyncio_loop ..." )
269263 self ._asyncio_loop .call_soon_threadsafe (self ._asyncio_loop .stop )
270264 self ._asyncio_thread .join ()
271- self ._asyncio_thread = None
272265 self ._logger .notice ("_asyncio_thread joined" )
266+ self ._stream = None
267+ self ._asyncio_thread = None
273268
274269 self ._logger .notice ("finish succeeded" )
275270 self ._logger .debug ("Microphone.finish LEAVE" )
276271
277272 return True
273+
274+ def _callback (
275+ self , input_data , frame_count , time_info , status_flags
276+ ): # pylint: disable=unused-argument
277+ """
278+ The callback used to process data in callback mode.
279+ """
280+ # dynamic import of pyaudio as not to force the requirements on the SDK (and users)
281+ import pyaudio # pylint: disable=import-outside-toplevel
282+
283+ if self ._exit .is_set ():
284+ self ._logger .notice ("_callback exit is Set. stopping..." )
285+ return None , pyaudio .paAbort
286+
287+ if input_data is None :
288+ self ._logger .warning ("input_data is None" )
289+ return None , pyaudio .paContinue
290+
291+ try :
292+ if self ._is_muted :
293+ size = len (input_data )
294+ input_data = b"\x00 " * size
295+
296+ self ._push_callback (input_data )
297+ except Exception as e :
298+ self ._logger .error ("Error while sending: %s" , str (e ))
299+ raise
300+
301+ return input_data , pyaudio .paContinue
0 commit comments