Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/gtk2/grecord.py
diff options
context:
space:
mode:
Diffstat (limited to 'gtk2/grecord.py')
-rw-r--r--gtk2/grecord.py244
1 files changed, 0 insertions, 244 deletions
diff --git a/gtk2/grecord.py b/gtk2/grecord.py
deleted file mode 100644
index 02fcbd3..0000000
--- a/gtk2/grecord.py
+++ /dev/null
@@ -1,244 +0,0 @@
-#Copyright (c) 2008, Media Modifications Ltd.
-#Copyright (c) 2011-12, Walter Bender
-
-#Permission is hereby granted, free of charge, to any person obtaining a copy
-#of this software and associated documentation files (the "Software"), to deal
-#in the Software without restriction, including without limitation the rights
-#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-#copies of the Software, and to permit persons to whom the Software is
-#furnished to do so, subject to the following conditions:
-
-#The above copyright notice and this permission notice shall be included in
-#all copies or substantial portions of the Software.
-
-#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-#THE SOFTWARE.
-
-import os
-import time
-
-import gtk
-import gst
-
-import logging
-_logger = logging.getLogger("portfolio-activity")
-
-import gobject
-gobject.threads_init()
-
-
-class Grecord:
-
- def __init__(self, parent):
- self._activity = parent
- self._eos_cb = None
-
- self._can_limit_framerate = False
- self._playing = False
-
- self._audio_transcode_handler = None
- self._transcode_id = None
-
- self._pipeline = gst.Pipeline("Record")
- self._create_audiobin()
-
- bus = self._pipeline.get_bus()
- bus.add_signal_watch()
- bus.connect('message', self._bus_message_handler)
-
- def _create_audiobin(self):
- src = gst.element_factory_make("alsasrc", "absrc")
-
- # attempt to use direct access to the 0,0 device, solving some A/V
- # sync issues
- src.set_property("device", "plughw:0,0")
- hwdev_available = src.set_state(gst.STATE_PAUSED) != \
- gst.STATE_CHANGE_FAILURE
- src.set_state(gst.STATE_NULL)
- if not hwdev_available:
- src.set_property("device", "default")
-
- srccaps = gst.Caps("audio/x-raw-int,rate=16000,channels=1,depth=16")
-
- # Guarantee perfect stream, important for A/V sync
- rate = gst.element_factory_make("audiorate")
-
- # Without a buffer here, gstreamer struggles at the start of the
- # recording and then the A/V sync is bad for the whole video
- # (possibly a gstreamer/ALSA bug -- even if it gets caught up, it
- # should be able to resync without problem).
- queue = gst.element_factory_make("queue", "audioqueue")
- queue.set_property("leaky", True) # prefer fresh data
- queue.set_property("max-size-time", 5000000000) # 5 seconds
- queue.set_property("max-size-buffers", 500)
- queue.connect("overrun", self._log_queue_overrun)
-
- enc = gst.element_factory_make("wavenc", "abenc")
-
- sink = gst.element_factory_make("filesink", "absink")
- sink.set_property("location",
- os.path.join(self._activity.get_activity_root(),
- 'instance', 'output.wav'))
-
- self._audiobin = gst.Bin("audiobin")
- self._audiobin.add(src, rate, queue, enc, sink)
-
- src.link(rate, srccaps)
- gst.element_link_many(rate, queue, enc, sink)
-
- def _log_queue_overrun(self, queue):
- 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 _get_state(self):
- return self._pipeline.get_state()[1]
-
- def stop_recording_audio(self):
- # We should be able to simply pause and remove the audiobin, but
- # this seems to cause a gstreamer segfault. So we stop the whole
- # pipeline while manipulating it.
- # http://dev.laptop.org/ticket/10183
- self._pipeline.set_state(gst.STATE_NULL)
- self._pipeline.remove(self._audiobin)
- self.play()
-
- audio_path = os.path.join(self._activity.get_activity_root(),
- 'instance', 'output.wav')
- if not os.path.exists(audio_path) or os.path.getsize(audio_path) <= 0:
- # FIXME: inform model of failure?
- _logger.error('output.wav does not exist or is empty')
- return
-
- line = 'filesrc location=' + audio_path + ' name=audioFilesrc ! \
-wavparse name=audioWavparse ! audioconvert name=audioAudioconvert ! \
-vorbisenc name=audioVorbisenc ! oggmux name=audioOggmux ! \
-filesink name=audioFilesink'
- self._audioline = gst.parse_launch(line)
-
- vorbis_enc = self._audioline.get_by_name('audioVorbisenc')
-
- audioFilesink = self._audioline.get_by_name('audioFilesink')
- audioOggFilepath = os.path.join(self._activity.get_activity_root(),
- 'instance', 'output.ogg')
- audioFilesink.set_property("location", audioOggFilepath)
-
- audioBus = self._audioline.get_bus()
- audioBus.add_signal_watch()
- self._audio_transcode_handler = audioBus.connect(
- 'message', self._onMuxedAudioMessageCb, self._audioline)
- self._transcode_id = gobject.timeout_add(200, self._transcodeUpdateCb,
- self._audioline)
- self._audiopos = 0
- self._audioline.set_state(gst.STATE_PLAYING)
-
- def transcoding_complete(self):
- # The EOS message is sometimes either not sent or not received.
- # So if the position in the stream is not advancing, assume EOS.
- if self._transcode_id is None:
- _logger.debug('EOS.... transcoding finished')
- return True
- else:
- position, duration = self._query_position(self._audioline)
- # _logger.debug('position: %s, duration: %s' % (str(position),
- # str(duration)))
- if position == duration:
- _logger.debug('We are done, even though we did not see EOS')
- self._clean_up_transcoding_pipeline(self._audioline)
- return True
- elif position == self._audiopos:
- _logger.debug('No progess, so assume we are done')
- self._clean_up_transcoding_pipeline(self._audioline)
- return True
- self._audiopos = position
- return False
-
- def blockedCb(self, x, y, z):
- pass
-
- def record_audio(self):
- # We should be able to add the audiobin on the fly, but unfortunately
- # this results in several seconds of silence being added at the start
- # of the recording. So we stop the whole pipeline while adjusting it.
- # SL#2040
- self._pipeline.set_state(gst.STATE_NULL)
- self._pipeline.add(self._audiobin)
- self.play()
-
- def _transcodeUpdateCb(self, pipe):
- position, duration = self._query_position(pipe)
- if position != gst.CLOCK_TIME_NONE:
- value = position * 100.0 / duration
- value = value / 100.0
- return True
-
- def _query_position(self, pipe):
- try:
- position, format = pipe.query_position(gst.FORMAT_TIME)
- except:
- position = gst.CLOCK_TIME_NONE
-
- try:
- duration, format = pipe.query_duration(gst.FORMAT_TIME)
- except:
- duration = gst.CLOCK_TIME_NONE
-
- return (position, duration)
-
- def _onMuxedAudioMessageCb(self, bus, message, pipe):
- # _logger.debug(message.type)
- if message.type != gst.MESSAGE_EOS:
- return True
- self._clean_up_transcoding_pipeline(pipe)
- return False
-
- def _clean_up_transcoding_pipeline(self, pipe):
- gobject.source_remove(self._audio_transcode_handler)
- self._audio_transcode_handler = None
- gobject.source_remove(self._transcode_id)
- self._transcode_id = None
- pipe.set_state(gst.STATE_NULL)
- pipe.get_bus().remove_signal_watch()
- pipe.get_bus().disable_sync_message_emission()
-
- wavFilepath = os.path.join(self._activity.get_activity_root(),
- 'instance', 'output.wav')
- os.remove(wavFilepath)
- return
-
- def _bus_message_handler(self, bus, message):
- t = message.type
- if t == gst.MESSAGE_EOS:
- if self._eos_cb:
- cb = self._eos_cb
- self._eos_cb = None
- cb()
- elif t == gst.MESSAGE_ERROR:
- # TODO: if we come out of suspend/resume with errors, then
- # get us back up and running... TODO: handle "No space
- # left on the resource.gstfilesink.c" err, debug =
- # message.parse_error()
- pass