Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/pysamples
diff options
context:
space:
mode:
authorWalter Bender <walter.bender@gmail.com>2011-04-15 15:51:59 (GMT)
committer Walter Bender <walter.bender@gmail.com>2011-04-15 15:51:59 (GMT)
commite474df3d4f8fece03b1e5d8fe8336d9bc6417cd9 (patch)
tree77527c800db0cc75800a1f60ef247ffed1d1e6d7 /pysamples
parent1f08f2f1563bfdfbffed127706794777287b7beb (diff)
code cleanup of gstreamer record example
Diffstat (limited to 'pysamples')
-rw-r--r--pysamples/grecord.py118
1 files changed, 58 insertions, 60 deletions
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()