Changeset 466
- Timestamp:
- 23-05-11 16:57:16 (2 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
-
ChangeLog (modified) (1 diff)
-
morituri/common/encode.py (modified) (10 diffs)
-
morituri/common/gstreamer.py (modified) (4 diffs)
-
morituri/test/test_common_encode.py (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ChangeLog
r465 r466 1 2011-05-23 Thomas Vander Stichele <thomas at apestaart dot org> 2 3 * morituri/test/test_common_encode.py: 4 Generate an actual file by spawning gst-launch; otherwise 5 with proper error handling we get an error from wavparse that 6 there is not enough data to typefind. 7 * morituri/common/gstreamer.py: 8 Move the gst import to start() and set it as a class attribute. 9 Document methods. 10 * morituri/common/encode.py: 11 Convert EncodeTask to a GstPipelineTask. 12 1 13 2011-05-23 Thomas Vander Stichele <thomas at apestaart dot org> 2 14 -
trunk/morituri/common/encode.py
r465 r466 26 26 import tempfile 27 27 28 from morituri.common import common, task, log 28 from morituri.common import common, task, log, gstreamer 29 29 30 30 class Profile(object): … … 123 123 ALL_PROFILES.update(LOSSY_PROFILES) 124 124 125 class EncodeTask( task.Task):125 class EncodeTask(gstreamer.GstPipelineTask): 126 126 """ 127 127 I am a task that encodes a .wav file. … … 159 159 self._profile.test() 160 160 161 def start(self, runner): 162 task.Task.start(self, runner) 163 164 # here to avoid import gst eating our options 165 import gst 166 167 desc = ''' 161 def getPipelineDesc(self): 162 return ''' 168 163 filesrc location="%s" ! 169 164 decodebin name=decoder ! … … 176 171 common.quoteParse(self._outpath).encode('utf-8')) 177 172 178 self.debug('creating pipeline: %r', desc) 179 self._pipeline = gst.parse_launch(desc) 180 181 tagger = self._pipeline.get_by_name('tagger') 173 def parsed(self): 174 tagger = self.pipeline.get_by_name('tagger') 182 175 183 176 # set tags … … 186 179 # See for example comment saying wavenc did not have it. 187 180 try: 188 tagger.merge_tags(self._taglist, gst.TAG_MERGE_APPEND)181 tagger.merge_tags(self._taglist, self.gst.TAG_MERGE_APPEND) 189 182 except AttributeError, e: 190 183 self.warning('Could not merge tags: %r', 191 184 log.getExceptionMessage(e)) 192 185 193 self.debug('pausing pipeline') 194 self._pipeline.set_state(gst.STATE_PAUSED) 195 self._pipeline.get_state() 196 self.debug('paused pipeline') 197 186 def paused(self): 198 187 # get length 199 identity = self. _pipeline.get_by_name('identity')188 identity = self.pipeline.get_by_name('identity') 200 189 self.debug('query duration') 201 190 try: 202 length, qformat = identity.query_duration( gst.FORMAT_DEFAULT)203 except gst.QueryError, e:191 length, qformat = identity.query_duration(self.gst.FORMAT_DEFAULT) 192 except self.gst.QueryError, e: 204 193 self.setException(e) 205 194 self.stop() … … 207 196 208 197 # wavparse 0.10.14 returns in bytes 209 if qformat == gst.FORMAT_BYTES:198 if qformat == self.gst.FORMAT_BYTES: 210 199 self.debug('query returned in BYTES format') 211 200 length /= 4 … … 213 202 self._length = length 214 203 215 # add eos handling 216 bus = self._pipeline.get_bus() 204 # set up level callbacks 205 # FIXME: publicize bus and reuse it instead of regetting and adding ? 206 bus = self.pipeline.get_bus() 217 207 bus.add_signal_watch() 218 bus.connect('message::eos', self._message_eos_cb) 219 220 # set up level callbacks 208 221 209 bus.connect('message::element', self._message_element_cb) 222 self._level = self. _pipeline.get_by_name('level')210 self._level = self.pipeline.get_by_name('level') 223 211 # add a probe so we can track progress 224 212 # we connect to level because this gives us offset in samples … … 226 214 srcpad.add_buffer_probe(self._probe_handler) 227 215 216 # FIXME: move to base class ? 228 217 self.debug('scheduling setting to play') 229 218 # since set_state returns non-False, adding it as timeout_add 230 219 # will repeatedly call it, and block the main loop; so 231 # gobject.timeout_add(0L, self. _pipeline.set_state,gst.STATE_PLAYING)220 # gobject.timeout_add(0L, self.pipeline.set_state, self.gst.STATE_PLAYING) 232 221 # would not work. 233 222 234 223 def play(): 235 self. _pipeline.set_state(gst.STATE_PLAYING)224 self.pipeline.set_state(self.gst.STATE_PLAYING) 236 225 return False 237 226 self.runner.schedule(0, play) 238 227 239 #self. _pipeline.set_state(gst.STATE_PLAYING)228 #self.pipeline.set_state(gst.STATE_PLAYING) 240 229 self.debug('scheduled setting to play') 241 230 … … 250 239 return True 251 240 252 def _message_eos_cb(self, bus, message):241 def bus_eos_cb(self, bus, message): 253 242 self.debug('eos, scheduling stop') 254 243 self.runner.schedule(0, self.stop) … … 271 260 self._peakdB = p 272 261 262 # FIXME: move to base class, have stopped handler ? 273 263 def stop(self): 274 # here to avoid import gst eating our options275 import gst276 277 264 self.debug('stopping') 278 265 self.debug('setting state to NULL') 279 self. _pipeline.set_state(gst.STATE_NULL)266 self.pipeline.set_state(self.gst.STATE_NULL) 280 267 self.debug('set state to NULL') 281 268 # FIXME: maybe this should move lower ? If used by BaseMultiTask, -
trunk/morituri/common/gstreamer.py
r457 r466 21 21 # along with morituri. If not, see <http://www.gnu.org/licenses/>. 22 22 23 import gst24 25 23 from morituri.common import common, task 26 24 … … 36 34 37 35 I handle errors and raise them appropriately. 36 37 @cvar gst: the GStreamer module, so code does not have to import gst 38 as a module in code everywhere to avoid option stealing. 38 39 """ 40 41 gst = None 42 39 43 def start(self, runner): 44 import gst 45 self.gst = gst 46 40 47 task.Task.start(self, runner) 41 48 desc = self.getPipelineDesc() 42 49 43 50 self.debug('creating pipeline %r', desc) 44 self.pipeline = gst.parse_launch(desc)51 self.pipeline = self.gst.parse_launch(desc) 45 52 46 53 self._bus = self.pipeline.get_bus() 47 gst.debug('got bus %r' % self._bus)54 self.gst.debug('got bus %r' % self._bus) 48 55 49 56 # a signal watch calls callbacks from an idle loop … … 60 67 61 68 self.debug('pausing pipeline') 62 self.pipeline.set_state( gst.STATE_PAUSED)69 self.pipeline.set_state(self.gst.STATE_PAUSED) 63 70 # FIXME: this can block 64 71 self.pipeline.get_state() … … 86 93 87 94 def bus_eos_cb(self, bus, message): 95 """ 96 Called synchronously (ie from messaging thread) on eos message. 97 98 Override me to handle eos 99 """ 88 100 pass 89 101 90 102 def bus_tag_cb(self, bus, message): 103 """ 104 Called synchronously (ie from messaging thread) on tag message. 105 106 Override me to handle tags. 107 """ 91 108 pass 92 109 93 110 def bus_error_cb(self, bus, message): 111 """ 112 Called synchronously (ie from messaging thread) on error message. 113 """ 94 114 exc = GstException(*message.parse_error()) 95 115 self.setAndRaiseException(exc) 96 gst.debug('error, scheduling stop') 116 # FIXME: why is this commented ? 117 # self.gst.debug('error, scheduling stop') 97 118 #self.runner.schedule(0, self.stop) -
trunk/morituri/test/test_common_encode.py
r401 r466 10 10 import gst 11 11 12 from morituri.test import common 12 from morituri.test import common as tcommon 13 13 14 from morituri.common import task, encode, log 14 from morituri.common import task, encode, log, common 15 15 16 class PathTestCase( common.TestCase):16 class PathTestCase(tcommon.TestCase): 17 17 def _testSuffix(self, suffix): 18 18 self.runner = task.SyncRunner(verbose=False) 19 fd, path = tempfile.mkstemp( 20 suffix=suffix) 19 fd, path = tempfile.mkstemp(suffix=suffix) 20 cmd = "gst-launch " \ 21 "audiotestsrc num-buffers=100 samplesperbuffer=1024 ! " \ 22 "audioconvert ! audio/x-raw-int,width=16,depth=16,channels =2 ! " \ 23 "wavenc ! " \ 24 "filesink location=\"%s\" > /dev/null 2>&1" % ( 25 common.quoteParse(path).encode('utf-8'), ) 26 os.system(cmd) 27 self.failUnless(os.path.exists(path)) 21 28 encodetask = encode.EncodeTask(path, path + '.out', 22 29 encode.WavProfile()) 23 e = self.assertRaises(task.TaskException, self.runner.run, 24 encodetask, verbose=False) 25 self.failUnless(isinstance(e.exception, gst.QueryError), 26 "%r is not a gst.QueryError" % e.exception) 30 self.runner.run(encodetask, verbose=False) 27 31 os.close(fd) 28 32 os.unlink(path) 29 33 os.unlink(path + '.out') 30 34 31 class UnicodePathTestCase(PathTestCase, common.UnicodeTestMixin):35 class UnicodePathTestCase(PathTestCase, tcommon.UnicodeTestMixin): 32 36 def testUnicodePath(self): 33 37 # this test makes sure we can checksum a unicode path … … 41 45 self._testSuffix(u'.morituri.test_encode.12" edit') 42 46 43 class TagReadTestCase( common.TestCase):47 class TagReadTestCase(tcommon.TestCase): 44 48 def testRead(self): 45 49 path = os.path.join(os.path.dirname(__file__), u'track.flac') … … 51 55 self.assertEquals(t.taglist['description'], 'audiotest wave') 52 56 53 class TagWriteTestCase( common.TestCase):57 class TagWriteTestCase(tcommon.TestCase): 54 58 def testWrite(self): 55 59 fd, inpath = tempfile.mkstemp(suffix=u'.morituri.tagwrite.flac') … … 82 86 os.unlink(outpath) 83 87 84 class SafeRetagTestCase( common.TestCase):88 class SafeRetagTestCase(tcommon.TestCase): 85 89 def setUp(self): 86 90 self._fd, self._path = tempfile.mkstemp(suffix=u'.morituri.retag.flac')
Note: See TracChangeset
for help on using the changeset viewer.
