From e474df3d4f8fece03b1e5d8fe8336d9bc6417cd9 Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Fri, 15 Apr 2011 15:51:59 +0000 Subject: code cleanup of gstreamer record example --- (limited to 'pysamples/grecord.py') diff --git a/pysamples/grecord.py b/pysamples/grecord.py index f5e2836..84b1a5c 100644 --- a/pysamples/grecord.py +++ b/pysamples/grecord.py @@ -5,8 +5,9 @@ # "extras" palette is selected. # Usage: Import this code into a Python (user-definable) block; Pass -# it 'start' to start recording; 'stop' to stop recording; 'play' -# to play back your recording; or 'save' to save to the Sugar Journal. +# it 'start' to start recording; 'stop' to stop recording; 'play' to +# play back your recording; or 'save' to save your recording to the +# Sugar Journal. def myblock(tw, arg): @@ -25,18 +26,21 @@ def myblock(tw, arg): from sugar.datastore import datastore from sugar import profile + from gettext import gettext as _ class Grecord: + ''' A class for creating a gstreamer session for recording audio. ''' def __init__(self, tw): - ''' Set up the stream. ''' + ''' Set up the stream. We save to a raw .wav file and then + convert the sound to .ogg for saving. ''' datapath = get_path(tw.parent, 'instance') self.capture_file = os.path.join(datapath, 'output.wav') self.save_file = os.path.join(datapath, 'output.ogg') self._eos_cb = None self._can_limit_framerate = False - self._playing = False + self._recording = False self._audio_transcode_handler = None self._transcode_id = None @@ -50,6 +54,7 @@ def myblock(tw, arg): bus.connect('message', self._bus_message_handler) def _create_audiobin(self): + ''' Assemble all the pieces we need. ''' src = gst.element_factory_make("alsasrc", "absrc") # attempt to use direct access to the 0,0 device, solving some A/V @@ -88,47 +93,47 @@ def myblock(tw, arg): gst.element_link_many(rate, queue, enc, sink) def _log_queue_overrun(self, queue): + ''' We use a buffer, which may overflow. ''' cbuffers = queue.get_property("current-level-buffers") cbytes = queue.get_property("current-level-bytes") ctime = queue.get_property("current-level-time") - def play(self): - if self._get_state() == gst.STATE_PLAYING: - return - - self._pipeline.set_state(gst.STATE_PLAYING) - self._playing = True - - def pause(self): - self._pipeline.set_state(gst.STATE_PAUSED) - self._playing = False - - def stop(self): - self._pipeline.set_state(gst.STATE_NULL) - self._playing = False - - def is_playing(self): - return self._playing + def is_recording(self): + ''' Are we recording? ''' + return self._recording def _get_state(self): + ''' What is the state of our gstreamer pipeline? ''' return self._pipeline.get_state()[1] + def start_recording_audio(self): + ''' Start the stream in order to start recording. ''' + if self._get_state() == gst.STATE_PLAYING: + return + self._pipeline.set_state(gst.STATE_PLAYING) + self._recording = True + def stop_recording_audio(self): - self.stop() + ''' Stop recording and then convert the results into a + .ogg file using a new stream. ''' + self._pipeline.set_state(gst.STATE_NULL) + self._recording = False - audio_path = self.capture_file - if not os.path.exists(audio_path) or \ - os.path.getsize(audio_path) <= 0: + if not os.path.exists(self.capture_file) or \ + os.path.getsize(self.capture_file) <= 0: return - line = 'filesrc location=' + audio_path + ' name=audioFilesrc ! wavparse name=audioWavparse ! audioconvert name=audioAudioconvert ! vorbisenc name=audioVorbisenc ! oggmux name=audioOggmux ! filesink name=audioFilesink' + # Remove previous transcoding results. + if os.path.exists(self.save_file): + os.remove(self.save_file) + + line = 'filesrc location=' + self.capture_file + ' name=audioFilesrc ! wavparse name=audioWavparse ! audioconvert name=audioAudioconvert ! vorbisenc name=audioVorbisenc ! oggmux name=audioOggmux ! filesink name=audioFilesink' audioline = gst.parse_launch(line) vorbis_enc = audioline.get_by_name('audioVorbisenc') audioFilesink = audioline.get_by_name('audioFilesink') - audioOggFilepath = self.save_file - audioFilesink.set_property("location", audioOggFilepath) + audioFilesink.set_property("location", self.save_file) audioBus = audioline.get_bus() audioBus.add_signal_watch() @@ -138,13 +143,8 @@ def myblock(tw, arg): 200, self._transcodeUpdateCb, audioline) audioline.set_state(gst.STATE_PLAYING) - def blockedCb(self, x, y, z): - pass - - def record_audio(self): - self.play() - def _transcodeUpdateCb(self, pipe): + ''' Where are we in the transcoding process? ''' position, duration = self._query_position(pipe) if position != gst.CLOCK_TIME_NONE: value = position * 100.0 / duration @@ -152,6 +152,7 @@ def myblock(tw, arg): return True def _query_position(self, pipe): + ''' Where are we in the stream? ''' try: position, format = pipe.query_position(gst.FORMAT_TIME) except: @@ -165,6 +166,7 @@ def myblock(tw, arg): return (position, duration) def _onMuxedAudioMessageCb(self, bus, message, pipe): + ''' Clean up at end of stream.''' if message.type != gst.MESSAGE_EOS: return True @@ -176,12 +178,11 @@ def myblock(tw, arg): pipe.get_bus().remove_signal_watch() pipe.get_bus().disable_sync_message_emission() - wavFilepath = self.capture_file - oggFilepath = self.save_file - os.remove( wavFilepath ) + os.remove(self.capture_file) return False def _bus_message_handler(self, bus, message): + ''' Handle any messages associated with the stream. ''' t = message.type if t == gst.MESSAGE_EOS: if self._eos_cb: @@ -195,35 +196,32 @@ def myblock(tw, arg): # message.parse_error() pass - # We store the stream as tw.grecord so that we can use it repeatedly. + # We store the audio-record stream instance as tw.grecord so that + # we can use it repeatedly. if not hasattr(tw, 'grecord'): tw.grecord = Grecord(tw) - # Sometime we need to pass multiple arguments, e.g., save, savename - savename = _('turtle audio recording') + # Sometime we need to parse multiple arguments, e.g., save, savename + save_name = _('Turtle Art') + ' ' + _('sound') if type(arg) == type([]): - cmd = arg[0] + cmd = arg[0].lower() if len(arg) > 1: - savename = str(arg[1]) + save_name = str(arg[1]) else: - cmd = arg + cmd = arg.lower() - if cmd == _('start'): - tw.grecord.record_audio() - elif cmd == _('stop'): - if os.path.exists(tw.grecord.save_file): - os.remove(tw.grecord.save_file) + if cmd == 'start' or cmd == _('start').lower(): + tw.grecord.start_recording_audio() + elif cmd == 'stop' or cmd == _('stop').lower(): tw.grecord.stop_recording_audio() - elif cmd == _('play'): + elif cmd == 'play' or cmd == _('play').lower(): play_audio_from_file(tw.lc, tw.grecord.save_file) - elif cmd == _('save'): - if os.path.exists(tw.grecord.save_file): - if tw.running_sugar: - dsobject = datastore.create() - dsobject.metadata['title'] = savename - dsobject.metadata['icon-color'] = \ - profile.get_color().to_string() - dsobject.metadata['mime_type'] = 'audio/ogg' - dsobject.set_file_path(tw.grecord.save_file) - datastore.write(dsobject) - dsobject.destroy() + elif cmd == 'save' or cmd == _('save').lower(): + if os.path.exists(tw.grecord.save_file) and tw.running_sugar: + dsobject = datastore.create() + dsobject.metadata['title'] = save_name + dsobject.metadata['icon-color'] = profile.get_color().to_string() + dsobject.metadata['mime_type'] = 'audio/ogg' + dsobject.set_file_path(tw.grecord.save_file) + datastore.write(dsobject) + dsobject.destroy() -- cgit v0.9.1