1 | <?xml version="1.0" encoding="UTF-8"?> |
---|
2 | <!DOCTYPE abiword PUBLIC "-//ABISOURCE//DTD AWML 1.0 Strict//EN" "http://www.abisource.com/awml.dtd"> |
---|
3 | <abiword template="false" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:math="http://www.w3.org/1998/Math/MathML" xid-max="229" xmlns:dc="http://purl.org/dc/elements/1.1/" fileformat="1.1" xmlns:svg="http://www.w3.org/2000/svg" xmlns:awml="http://www.abisource.com/awml.dtd" xmlns="http://www.abisource.com/awml.dtd" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.8.4" xml:space="preserve" props="dom-dir:ltr; document-footnote-restart-section:0; document-endnote-type:numeric; document-endnote-place-enddoc:1; document-endnote-initial:1; lang:en-US; document-endnote-restart-section:0; document-footnote-restart-page:0; document-footnote-type:numeric; document-footnote-initial:1; document-endnote-place-endsection:0"> |
---|
4 | <!-- ======================================================================== --> |
---|
5 | <!-- This file is an AbiWord document. --> |
---|
6 | <!-- AbiWord is a free, Open Source word processor. --> |
---|
7 | <!-- More information about AbiWord is available at http://www.abisource.com/ --> |
---|
8 | <!-- You should not edit this file by hand. --> |
---|
9 | <!-- ======================================================================== --> |
---|
10 | |
---|
11 | <metadata> |
---|
12 | <m key="dc.format">application/x-abiword</m> |
---|
13 | <m key="abiword.generator">AbiWord</m> |
---|
14 | </metadata> |
---|
15 | <styles> |
---|
16 | <s type="P" name="Normal" basedon="" followedby="Current Settings" props="font-family:Liberation Serif; margin-top:0pt; font-variant:normal; margin-left:0pt; text-indent:0in; widows:2; font-style:normal; font-weight:normal; text-decoration:none; color:000000; line-height:1.0; text-align:left; margin-bottom:0pt; text-position:normal; margin-right:0pt; bgcolor:transparent; font-size:12pt; font-stretch:normal"/> |
---|
17 | </styles> |
---|
18 | <pagesize pagetype="A4" orientation="portrait" width="210.000000" height="297.000000" units="mm" page-scale="1.000000"/> |
---|
19 | <section xid="1"> |
---|
20 | <p style="Normal" xid="2" props="text-align:left; dom-dir:ltr">#Copyright (c) 2008, Media Modifications Ltd.</p> |
---|
21 | <p style="Normal" xid="3" props="text-align:left; dom-dir:ltr">#Copyright (c) 2011, Walter Bender</p> |
---|
22 | <p style="Normal" xid="4"><c></c></p> |
---|
23 | <p style="Normal" xid="5" props="text-align:left; dom-dir:ltr"># This procedure is invoked when the user-definable block on the</p> |
---|
24 | <p style="Normal" xid="6" props="text-align:left; dom-dir:ltr"># "extras" palette is selected.</p> |
---|
25 | <p style="Normal" xid="7"><c></c></p> |
---|
26 | <p style="Normal" xid="8" props="text-align:left; dom-dir:ltr"># Usage: Import this code into a Python (user-definable) block; Pass</p> |
---|
27 | <p style="Normal" xid="9" props="text-align:left; dom-dir:ltr"># it 'start' to start recording; 'stop' to stop recording; 'play' to</p> |
---|
28 | <p style="Normal" xid="10" props="text-align:left; dom-dir:ltr"># play back your recording; or 'save' to save your recording to the</p> |
---|
29 | <p style="Normal" xid="11" props="text-align:left; dom-dir:ltr"># Sugar Journal.</p> |
---|
30 | <p style="Normal" xid="12"><c></c></p> |
---|
31 | <p style="Normal" xid="13"><c></c></p> |
---|
32 | <p style="Normal" xid="14" props="text-align:left; dom-dir:ltr">def myblock(tw, arg):</p> |
---|
33 | <p style="Normal" xid="15" props="text-align:left; dom-dir:ltr"> ''' Record and playback a sound (Sugar only) '''</p> |
---|
34 | <p style="Normal" xid="16" props="text-align:left; dom-dir:ltr"> import os</p> |
---|
35 | <p style="Normal" xid="17" props="text-align:left; dom-dir:ltr"> import time</p> |
---|
36 | <p style="Normal" xid="18"><c></c></p> |
---|
37 | <p style="Normal" xid="19" props="text-align:left; dom-dir:ltr"> import gtk</p> |
---|
38 | <p style="Normal" xid="20" props="text-align:left; dom-dir:ltr"> import gst</p> |
---|
39 | <p style="Normal" xid="21"><c></c></p> |
---|
40 | <p style="Normal" xid="22" props="text-align:left; dom-dir:ltr"> import gobject</p> |
---|
41 | <p style="Normal" xid="23" props="text-align:left; dom-dir:ltr"> gobject.threads_init()</p> |
---|
42 | <p style="Normal" xid="24"><c></c></p> |
---|
43 | <p style="Normal" xid="25" props="text-align:left; dom-dir:ltr"> from TurtleArt.tautils import get_path</p> |
---|
44 | <p style="Normal" xid="26" props="text-align:left; dom-dir:ltr"> from TurtleArt.tagplay import play_audio_from_file</p> |
---|
45 | <p style="Normal" xid="27" props="text-align:left; dom-dir:ltr"> from sugar.datastore import datastore</p> |
---|
46 | <p style="Normal" xid="28" props="text-align:left; dom-dir:ltr"> from sugar import profile</p> |
---|
47 | <p style="Normal" xid="29"><c></c></p> |
---|
48 | <p style="Normal" xid="30" props="text-align:left; dom-dir:ltr"> from gettext import gettext as _</p> |
---|
49 | <p style="Normal" xid="31"><c></c></p> |
---|
50 | <p style="Normal" xid="32" props="text-align:left; dom-dir:ltr"> class Grecord:</p> |
---|
51 | <p style="Normal" xid="33" props="text-align:left; dom-dir:ltr"> ''' A class for creating a gstreamer session for recording audio. '''</p> |
---|
52 | <p style="Normal" xid="34"><c></c></p> |
---|
53 | <p style="Normal" xid="35" props="text-align:left; dom-dir:ltr"> def __init__(self, tw):</p> |
---|
54 | <p style="Normal" xid="36" props="text-align:left; dom-dir:ltr"> ''' Set up the stream. We save to a raw .wav file and then</p> |
---|
55 | <p style="Normal" xid="37" props="text-align:left; dom-dir:ltr"> convert the sound to .ogg for saving. '''</p> |
---|
56 | <p style="Normal" xid="38" props="text-align:left; dom-dir:ltr"> datapath = get_path(tw.parent, 'instance')</p> |
---|
57 | <p style="Normal" xid="39" props="text-align:left; dom-dir:ltr"> self.capture_file = os.path.join(datapath, 'output.wav')</p> |
---|
58 | <p style="Normal" xid="40" props="text-align:left; dom-dir:ltr"> self.save_file = os.path.join(datapath, 'output.ogg')</p> |
---|
59 | <p style="Normal" xid="41" props="text-align:left; dom-dir:ltr"> self._eos_cb = None</p> |
---|
60 | <p style="Normal" xid="42"><c></c></p> |
---|
61 | <p style="Normal" xid="43" props="text-align:left; dom-dir:ltr"> self._can_limit_framerate = False</p> |
---|
62 | <p style="Normal" xid="44" props="text-align:left; dom-dir:ltr"> self._recording = False</p> |
---|
63 | <p style="Normal" xid="45"><c></c></p> |
---|
64 | <p style="Normal" xid="46" props="text-align:left; dom-dir:ltr"> self._audio_transcode_handler = None</p> |
---|
65 | <p style="Normal" xid="47" props="text-align:left; dom-dir:ltr"> self._transcode_id = None</p> |
---|
66 | <p style="Normal" xid="48"><c></c></p> |
---|
67 | <p style="Normal" xid="49" props="text-align:left; dom-dir:ltr"> self._pipeline = gst.Pipeline("Record")</p> |
---|
68 | <p style="Normal" xid="50" props="text-align:left; dom-dir:ltr"> self._create_audiobin()</p> |
---|
69 | <p style="Normal" xid="51" props="text-align:left; dom-dir:ltr"> self._pipeline.add(self._audiobin)</p> |
---|
70 | <p style="Normal" xid="52"><c></c></p> |
---|
71 | <p style="Normal" xid="53" props="text-align:left; dom-dir:ltr"> bus = self._pipeline.get_bus()</p> |
---|
72 | <p style="Normal" xid="54" props="text-align:left; dom-dir:ltr"> bus.add_signal_watch()</p> |
---|
73 | <p style="Normal" xid="55" props="text-align:left; dom-dir:ltr"> bus.connect('message', self._bus_message_handler)</p> |
---|
74 | <p style="Normal" xid="56"><c></c></p> |
---|
75 | <p style="Normal" xid="57" props="text-align:left; dom-dir:ltr"> def _create_audiobin(self):</p> |
---|
76 | <p style="Normal" xid="58" props="text-align:left; dom-dir:ltr"> ''' Assemble all the pieces we need. '''</p> |
---|
77 | <p style="Normal" xid="59" props="text-align:left; dom-dir:ltr"> src = gst.element_factory_make("alsasrc", "absrc")</p> |
---|
78 | <p style="Normal" xid="60"><c></c></p> |
---|
79 | <p style="Normal" xid="61" props="text-align:left; dom-dir:ltr"> # attempt to use direct access to the 0,0 device, solving some A/V</p> |
---|
80 | <p style="Normal" xid="62" props="text-align:left; dom-dir:ltr"> # sync issues</p> |
---|
81 | <p style="Normal" xid="63" props="text-align:left; dom-dir:ltr"> src.set_property("device", "plughw:0,0")</p> |
---|
82 | <p style="Normal" xid="64" props="text-align:left; dom-dir:ltr"> hwdev_available = src.set_state(gst.STATE_PAUSED) != \</p> |
---|
83 | <p style="Normal" xid="65" props="text-align:left; dom-dir:ltr"> gst.STATE_CHANGE_FAILURE</p> |
---|
84 | <p style="Normal" xid="66" props="text-align:left; dom-dir:ltr"> src.set_state(gst.STATE_NULL)</p> |
---|
85 | <p style="Normal" xid="67" props="text-align:left; dom-dir:ltr"> if not hwdev_available:</p> |
---|
86 | <p style="Normal" xid="68" props="text-align:left; dom-dir:ltr"> src.set_property("device", "default")</p> |
---|
87 | <p style="Normal" xid="69"><c></c></p> |
---|
88 | <p style="Normal" xid="70" props="text-align:left; dom-dir:ltr"> srccaps = gst.Caps("audio/x-raw-int,rate=16000,channels=1,depth=16")</p> |
---|
89 | <p style="Normal" xid="71"><c></c></p> |
---|
90 | <p style="Normal" xid="72" props="text-align:left; dom-dir:ltr"> # guarantee perfect stream, important for A/V sync</p> |
---|
91 | <p style="Normal" xid="73" props="text-align:left; dom-dir:ltr"> rate = gst.element_factory_make("audiorate")</p> |
---|
92 | <p style="Normal" xid="74"><c></c></p> |
---|
93 | <p style="Normal" xid="75" props="text-align:left; dom-dir:ltr"> # without a buffer here, gstreamer struggles at the start of the</p> |
---|
94 | <p style="Normal" xid="76" props="text-align:left; dom-dir:ltr"> # recording and then the A/V sync is bad for the whole video</p> |
---|
95 | <p style="Normal" xid="77" props="text-align:left; dom-dir:ltr"> # (possibly a gstreamer/ALSA bug -- even if it gets caught up, it</p> |
---|
96 | <p style="Normal" xid="78" props="text-align:left; dom-dir:ltr"> # should be able to resync without problem)</p> |
---|
97 | <p style="Normal" xid="79" props="text-align:left; dom-dir:ltr"> queue = gst.element_factory_make("queue", "audioqueue")</p> |
---|
98 | <p style="Normal" xid="80" props="text-align:left; dom-dir:ltr"> queue.set_property("leaky", True) # prefer fresh data</p> |
---|
99 | <p style="Normal" xid="81" props="text-align:left; dom-dir:ltr"> queue.set_property("max-size-time", 5000000000) # 5 seconds</p> |
---|
100 | <p style="Normal" xid="82" props="text-align:left; dom-dir:ltr"> queue.set_property("max-size-buffers", 500)</p> |
---|
101 | <p style="Normal" xid="83" props="text-align:left; dom-dir:ltr"> queue.connect("overrun", self._log_queue_overrun)</p> |
---|
102 | <p style="Normal" xid="84"><c></c></p> |
---|
103 | <p style="Normal" xid="85" props="text-align:left; dom-dir:ltr"> enc = gst.element_factory_make("wavenc", "abenc")</p> |
---|
104 | <p style="Normal" xid="86"><c></c></p> |
---|
105 | <p style="Normal" xid="87" props="text-align:left; dom-dir:ltr"> sink = gst.element_factory_make("filesink", "absink")</p> |
---|
106 | <p style="Normal" xid="88" props="text-align:left; dom-dir:ltr"> sink.set_property("location", self.capture_file)</p> |
---|
107 | <p style="Normal" xid="89"><c></c></p> |
---|
108 | <p style="Normal" xid="90" props="text-align:left; dom-dir:ltr"> self._audiobin = gst.Bin("audiobin")</p> |
---|
109 | <p style="Normal" xid="91" props="text-align:left; dom-dir:ltr"> self._audiobin.add(src, rate, queue, enc, sink)</p> |
---|
110 | <p style="Normal" xid="92"><c></c></p> |
---|
111 | <p style="Normal" xid="93" props="text-align:left; dom-dir:ltr"> src.link(rate, srccaps)</p> |
---|
112 | <p style="Normal" xid="94" props="text-align:left; dom-dir:ltr"> gst.element_link_many(rate, queue, enc, sink)</p> |
---|
113 | <p style="Normal" xid="95"><c></c></p> |
---|
114 | <p style="Normal" xid="96" props="text-align:left; dom-dir:ltr"> def _log_queue_overrun(self, queue):</p> |
---|
115 | <p style="Normal" xid="97" props="text-align:left; dom-dir:ltr"> ''' We use a buffer, which may overflow. '''</p> |
---|
116 | <p style="Normal" xid="98" props="text-align:left; dom-dir:ltr"> cbuffers = queue.get_property("current-level-buffers")</p> |
---|
117 | <p style="Normal" xid="99" props="text-align:left; dom-dir:ltr"> cbytes = queue.get_property("current-level-bytes")</p> |
---|
118 | <p style="Normal" xid="100" props="text-align:left; dom-dir:ltr"> ctime = queue.get_property("current-level-time")</p> |
---|
119 | <p style="Normal" xid="101"> </p> |
---|
120 | <p style="Normal" xid="102" props="text-align:left; dom-dir:ltr"> def is_recording(self):</p> |
---|
121 | <p style="Normal" xid="103" props="text-align:left; dom-dir:ltr"> ''' Are we recording? '''</p> |
---|
122 | <p style="Normal" xid="104" props="text-align:left; dom-dir:ltr"> return self._recording</p> |
---|
123 | <p style="Normal" xid="105"><c></c></p> |
---|
124 | <p style="Normal" xid="106" props="text-align:left; dom-dir:ltr"> def _get_state(self):</p> |
---|
125 | <p style="Normal" xid="107" props="text-align:left; dom-dir:ltr"> ''' What is the state of our gstreamer pipeline? '''</p> |
---|
126 | <p style="Normal" xid="108" props="text-align:left; dom-dir:ltr"> return self._pipeline.get_state()[1]</p> |
---|
127 | <p style="Normal" xid="109"><c></c></p> |
---|
128 | <p style="Normal" xid="110" props="text-align:left; dom-dir:ltr"> def start_recording_audio(self):</p> |
---|
129 | <p style="Normal" xid="111" props="text-align:left; dom-dir:ltr"> ''' Start the stream in order to start recording. '''</p> |
---|
130 | <p style="Normal" xid="112" props="text-align:left; dom-dir:ltr"> if self._get_state() == gst.STATE_PLAYING:</p> |
---|
131 | <p style="Normal" xid="113" props="text-align:left; dom-dir:ltr"> return</p> |
---|
132 | <p style="Normal" xid="114" props="text-align:left; dom-dir:ltr"> self._pipeline.set_state(gst.STATE_PLAYING)</p> |
---|
133 | <p style="Normal" xid="115" props="text-align:left; dom-dir:ltr"> self._recording = True</p> |
---|
134 | <p style="Normal" xid="116"><c></c></p> |
---|
135 | <p style="Normal" xid="117" props="text-align:left; dom-dir:ltr"> def stop_recording_audio(self):</p> |
---|
136 | <p style="Normal" xid="118" props="text-align:left; dom-dir:ltr"> ''' Stop recording and then convert the results into a</p> |
---|
137 | <p style="Normal" xid="119" props="text-align:left; dom-dir:ltr"> .ogg file using a new stream. '''</p> |
---|
138 | <p style="Normal" xid="120" props="text-align:left; dom-dir:ltr"> self._pipeline.set_state(gst.STATE_NULL)</p> |
---|
139 | <p style="Normal" xid="121" props="text-align:left; dom-dir:ltr"> self._recording = False</p> |
---|
140 | <p style="Normal" xid="122"><c></c></p> |
---|
141 | <p style="Normal" xid="123" props="text-align:left; dom-dir:ltr"> if not os.path.exists(self.capture_file) or \</p> |
---|
142 | <p style="Normal" xid="124" props="text-align:left; dom-dir:ltr"> os.path.getsize(self.capture_file) <= 0:</p> |
---|
143 | <p style="Normal" xid="125" props="text-align:left; dom-dir:ltr"> return</p> |
---|
144 | <p style="Normal" xid="126"><c></c></p> |
---|
145 | <p style="Normal" xid="127" props="text-align:left; dom-dir:ltr"> # Remove previous transcoding results.</p> |
---|
146 | <p style="Normal" xid="128" props="text-align:left; dom-dir:ltr"> if os.path.exists(self.save_file):</p> |
---|
147 | <p style="Normal" xid="129" props="text-align:left; dom-dir:ltr"> os.remove(self.save_file)</p> |
---|
148 | <p style="Normal" xid="130"><c></c></p> |
---|
149 | <p style="Normal" xid="131" props="text-align:left; dom-dir:ltr"> line = 'filesrc location=' + self.capture_file + ' name=audioFilesrc ! wavparse name=audioWavparse ! audioconvert name=audioAudioconvert ! vorbisenc name=audioVorbisenc ! oggmux name=audioOggmux ! filesink name=audioFilesink'</p> |
---|
150 | <p style="Normal" xid="132" props="text-align:left; dom-dir:ltr"> audioline = gst.parse_launch(line)</p> |
---|
151 | <p style="Normal" xid="133"><c></c></p> |
---|
152 | <p style="Normal" xid="134" props="text-align:left; dom-dir:ltr"> vorbis_enc = audioline.get_by_name('audioVorbisenc')</p> |
---|
153 | <p style="Normal" xid="135"><c></c></p> |
---|
154 | <p style="Normal" xid="136" props="text-align:left; dom-dir:ltr"> audioFilesink = audioline.get_by_name('audioFilesink')</p> |
---|
155 | <p style="Normal" xid="137" props="text-align:left; dom-dir:ltr"> audioFilesink.set_property("location", self.save_file)</p> |
---|
156 | <p style="Normal" xid="138"><c></c></p> |
---|
157 | <p style="Normal" xid="139" props="text-align:left; dom-dir:ltr"> audioBus = audioline.get_bus()</p> |
---|
158 | <p style="Normal" xid="140" props="text-align:left; dom-dir:ltr"> audioBus.add_signal_watch()</p> |
---|
159 | <p style="Normal" xid="141" props="text-align:left; dom-dir:ltr"> self._audio_transcode_handler = audioBus.connect(</p> |
---|
160 | <p style="Normal" xid="142" props="text-align:left; dom-dir:ltr"> 'message', self._onMuxedAudioMessageCb, audioline)</p> |
---|
161 | <p style="Normal" xid="143" props="text-align:left; dom-dir:ltr"> self._transcode_id = gobject.timeout_add(</p> |
---|
162 | <p style="Normal" xid="144" props="text-align:left; dom-dir:ltr"> 200, self._transcodeUpdateCb, audioline)</p> |
---|
163 | <p style="Normal" xid="145" props="text-align:left; dom-dir:ltr"> audioline.set_state(gst.STATE_PLAYING)</p> |
---|
164 | <p style="Normal" xid="146"><c></c></p> |
---|
165 | <p style="Normal" xid="147" props="text-align:left; dom-dir:ltr"> def _transcodeUpdateCb(self, pipe):</p> |
---|
166 | <p style="Normal" xid="148" props="text-align:left; dom-dir:ltr"> ''' Where are we in the transcoding process? '''</p> |
---|
167 | <p style="Normal" xid="149" props="text-align:left; dom-dir:ltr"> position, duration = self._query_position(pipe)</p> |
---|
168 | <p style="Normal" xid="150" props="text-align:left; dom-dir:ltr"> if position != gst.CLOCK_TIME_NONE:</p> |
---|
169 | <p style="Normal" xid="151" props="text-align:left; dom-dir:ltr"> value = position * 100.0 / duration</p> |
---|
170 | <p style="Normal" xid="152" props="text-align:left; dom-dir:ltr"> value = value/100.0</p> |
---|
171 | <p style="Normal" xid="153" props="text-align:left; dom-dir:ltr"> return True</p> |
---|
172 | <p style="Normal" xid="154"><c></c></p> |
---|
173 | <p style="Normal" xid="155" props="text-align:left; dom-dir:ltr"> def _query_position(self, pipe):</p> |
---|
174 | <p style="Normal" xid="156" props="text-align:left; dom-dir:ltr"> ''' Where are we in the stream? '''</p> |
---|
175 | <p style="Normal" xid="157" props="text-align:left; dom-dir:ltr"> try:</p> |
---|
176 | <p style="Normal" xid="158" props="text-align:left; dom-dir:ltr"> position, format = pipe.query_position(gst.FORMAT_TIME)</p> |
---|
177 | <p style="Normal" xid="159" props="text-align:left; dom-dir:ltr"> except:</p> |
---|
178 | <p style="Normal" xid="160" props="text-align:left; dom-dir:ltr"> position = gst.CLOCK_TIME_NONE</p> |
---|
179 | <p style="Normal" xid="161"><c></c></p> |
---|
180 | <p style="Normal" xid="162" props="text-align:left; dom-dir:ltr"> try:</p> |
---|
181 | <p style="Normal" xid="163" props="text-align:left; dom-dir:ltr"> duration, format = pipe.query_duration(gst.FORMAT_TIME)</p> |
---|
182 | <p style="Normal" xid="164" props="text-align:left; dom-dir:ltr"> except:</p> |
---|
183 | <p style="Normal" xid="165" props="text-align:left; dom-dir:ltr"> duration = gst.CLOCK_TIME_NONE</p> |
---|
184 | <p style="Normal" xid="166"><c></c></p> |
---|
185 | <p style="Normal" xid="167" props="text-align:left; dom-dir:ltr"> return (position, duration)</p> |
---|
186 | <p style="Normal" xid="168"><c></c></p> |
---|
187 | <p style="Normal" xid="169" props="text-align:left; dom-dir:ltr"> def _onMuxedAudioMessageCb(self, bus, message, pipe):</p> |
---|
188 | <p style="Normal" xid="170" props="text-align:left; dom-dir:ltr"> ''' Clean up at end of stream.'''</p> |
---|
189 | <p style="Normal" xid="171" props="text-align:left; dom-dir:ltr"> if message.type != gst.MESSAGE_EOS:</p> |
---|
190 | <p style="Normal" xid="172" props="text-align:left; dom-dir:ltr"> return True</p> |
---|
191 | <p style="Normal" xid="173"><c></c></p> |
---|
192 | <p style="Normal" xid="174" props="text-align:left; dom-dir:ltr"> gobject.source_remove(self._audio_transcode_handler)</p> |
---|
193 | <p style="Normal" xid="175" props="text-align:left; dom-dir:ltr"> self._audio_transcode_handler = None</p> |
---|
194 | <p style="Normal" xid="176" props="text-align:left; dom-dir:ltr"> gobject.source_remove(self._transcode_id)</p> |
---|
195 | <p style="Normal" xid="177" props="text-align:left; dom-dir:ltr"> self._transcode_id = None</p> |
---|
196 | <p style="Normal" xid="178" props="text-align:left; dom-dir:ltr"> pipe.set_state(gst.STATE_NULL)</p> |
---|
197 | <p style="Normal" xid="179" props="text-align:left; dom-dir:ltr"> pipe.get_bus().remove_signal_watch()</p> |
---|
198 | <p style="Normal" xid="180" props="text-align:left; dom-dir:ltr"> pipe.get_bus().disable_sync_message_emission()</p> |
---|
199 | <p style="Normal" xid="181"><c></c></p> |
---|
200 | <p style="Normal" xid="182" props="text-align:left; dom-dir:ltr"> os.remove(self.capture_file)</p> |
---|
201 | <p style="Normal" xid="183" props="text-align:left; dom-dir:ltr"> return False</p> |
---|
202 | <p style="Normal" xid="184"><c></c></p> |
---|
203 | <p style="Normal" xid="185" props="text-align:left; dom-dir:ltr"> def _bus_message_handler(self, bus, message):</p> |
---|
204 | <p style="Normal" xid="186" props="text-align:left; dom-dir:ltr"> ''' Handle any messages associated with the stream. '''</p> |
---|
205 | <p style="Normal" xid="187" props="text-align:left; dom-dir:ltr"> t = message.type</p> |
---|
206 | <p style="Normal" xid="188" props="text-align:left; dom-dir:ltr"> if t == gst.MESSAGE_EOS:</p> |
---|
207 | <p style="Normal" xid="189" props="text-align:left; dom-dir:ltr"> if self._eos_cb:</p> |
---|
208 | <p style="Normal" xid="190" props="text-align:left; dom-dir:ltr"> cb = self._eos_cb</p> |
---|
209 | <p style="Normal" xid="191" props="text-align:left; dom-dir:ltr"> self._eos_cb = None</p> |
---|
210 | <p style="Normal" xid="192" props="text-align:left; dom-dir:ltr"> cb()</p> |
---|
211 | <p style="Normal" xid="193" props="text-align:left; dom-dir:ltr"> elif t == gst.MESSAGE_ERROR:</p> |
---|
212 | <p style="Normal" xid="194" props="text-align:left; dom-dir:ltr"> # TODO: if we come out of suspend/resume with errors, then</p> |
---|
213 | <p style="Normal" xid="195" props="text-align:left; dom-dir:ltr"> # get us back up and running... TODO: handle "No space</p> |
---|
214 | <p style="Normal" xid="196" props="text-align:left; dom-dir:ltr"> # left on the resource.gstfilesink.c" err, debug =</p> |
---|
215 | <p style="Normal" xid="197" props="text-align:left; dom-dir:ltr"> # message.parse_error()</p> |
---|
216 | <p style="Normal" xid="198" props="text-align:left; dom-dir:ltr"> pass</p> |
---|
217 | <p style="Normal" xid="199"><c></c></p> |
---|
218 | <p style="Normal" xid="200" props="text-align:left; dom-dir:ltr"> # We store the audio-record stream instance as tw.grecord so that</p> |
---|
219 | <p style="Normal" xid="201" props="text-align:left; dom-dir:ltr"> # we can use it repeatedly.</p> |
---|
220 | <p style="Normal" xid="202" props="text-align:left; dom-dir:ltr"> if not hasattr(tw, 'grecord'):</p> |
---|
221 | <p style="Normal" xid="203" props="text-align:left; dom-dir:ltr"> tw.grecord = Grecord(tw)</p> |
---|
222 | <p style="Normal" xid="204"><c></c></p> |
---|
223 | <p style="Normal" xid="205" props="text-align:left; dom-dir:ltr"> # Sometime we need to parse multiple arguments, e.g., save, savename</p> |
---|
224 | <p style="Normal" xid="206" props="text-align:left; dom-dir:ltr"> save_name = _('Turtle Art') + ' ' + _('sound')</p> |
---|
225 | <p style="Normal" xid="207" props="text-align:left; dom-dir:ltr"> if type(arg) == type([]):</p> |
---|
226 | <p style="Normal" xid="208" props="text-align:left; dom-dir:ltr"> cmd = arg[0].lower()</p> |
---|
227 | <p style="Normal" xid="209" props="text-align:left; dom-dir:ltr"> if len(arg) > 1:</p> |
---|
228 | <p style="Normal" xid="210" props="text-align:left; dom-dir:ltr"> save_name = str(arg[1])</p> |
---|
229 | <p style="Normal" xid="211" props="text-align:left; dom-dir:ltr"> else:</p> |
---|
230 | <p style="Normal" xid="212" props="text-align:left; dom-dir:ltr"> cmd = arg.lower()</p> |
---|
231 | <p style="Normal" xid="213"><c></c></p> |
---|
232 | <p style="Normal" xid="214" props="text-align:left; dom-dir:ltr"> if cmd == 'start' or cmd == _('start').lower():</p> |
---|
233 | <p style="Normal" xid="215" props="text-align:left; dom-dir:ltr"> tw.grecord.start_recording_audio()</p> |
---|
234 | <p style="Normal" xid="216" props="text-align:left; dom-dir:ltr"> elif cmd == 'stop' or cmd == _('stop').lower():</p> |
---|
235 | <p style="Normal" xid="217" props="text-align:left; dom-dir:ltr"> tw.grecord.stop_recording_audio()</p> |
---|
236 | <p style="Normal" xid="218" props="text-align:left; dom-dir:ltr"> elif cmd == 'play' or cmd == _('play').lower():</p> |
---|
237 | <p style="Normal" xid="219" props="text-align:left; dom-dir:ltr"> play_audio_from_file(tw.lc, tw.grecord.save_file)</p> |
---|
238 | <p style="Normal" xid="220" props="text-align:left; dom-dir:ltr"> elif cmd == 'save' or cmd == _('save').lower():</p> |
---|
239 | <p style="Normal" xid="221" props="text-align:left; dom-dir:ltr"> if os.path.exists(tw.grecord.save_file) and tw.running_sugar:</p> |
---|
240 | <p style="Normal" xid="222" props="text-align:left; dom-dir:ltr"> dsobject = datastore.create()</p> |
---|
241 | <p style="Normal" xid="223" props="text-align:left; dom-dir:ltr"> dsobject.metadata['title'] = save_name</p> |
---|
242 | <p style="Normal" xid="224" props="text-align:left; dom-dir:ltr"> dsobject.metadata['icon-color'] = profile.get_color().to_string()</p> |
---|
243 | <p style="Normal" xid="225" props="text-align:left; dom-dir:ltr"> dsobject.metadata['mime_type'] = 'audio/ogg'</p> |
---|
244 | <p style="Normal" xid="226" props="text-align:left; dom-dir:ltr"> dsobject.set_file_path(tw.grecord.save_file)</p> |
---|
245 | <p style="Normal" xid="227" props="text-align:left; dom-dir:ltr"> datastore.write(dsobject)</p> |
---|
246 | <p style="Normal" xid="228" props="text-align:left; dom-dir:ltr"> dsobject.destroy()</p> |
---|
247 | <p style="Normal" xid="229"></p> |
---|
248 | </section> |
---|
249 | </abiword> |
---|