~ubuntu-branches/ubuntu/trusty/serpentine/trusty

« back to all changes in this revision

Viewing changes to serpentine/audio.py

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2006-03-03 11:12:42 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060303111242-01ogkka2273vre4x
Tags: 0.6.91-0ubuntu1
New upstream version (UVF exception approved by mdz)

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
This module contains operations to convert sound files to WAV and to
23
23
retrieve a their metadata.
24
24
"""
 
25
if __name__ == '__main__':
 
26
    try:
 
27
        import pygst
 
28
        pygst.require("0.10")
 
29
    except ImportError:
 
30
        pass
25
31
 
26
32
import threading
27
33
import gst
28
34
import gobject
29
35
import operations
30
36
 
 
37
GVFS_SRC = "gnomevfssrc"
 
38
FILE_SRC = "filesrc"
 
39
 
 
40
class ElementNotFoundError(KeyError):
 
41
    """This error is thrown when an element is not found"""
 
42
 
 
43
# Versions below 0.9 do not raise an exception when the element is not found
 
44
if gst.gst_version < (0, 9):
 
45
    def safe_element_factory_make(*args, **kwargs):
 
46
        element = gst.element_factory_make(*args, **kwargs)
 
47
        if element is None:
 
48
            raise ElementNotFoundError(args)
 
49
        return element
 
50
# New versions >= 0.9 already raise an exception, so there's not a big problem
 
51
else:
 
52
    safe_element_factory_make = gst.element_factory_make
 
53
    
31
54
class GstPlayingFailledError(StandardError):
32
55
    """This error is thrown when we can't set the state to PLAYING"""
33
56
    
137
160
    def start (self):
138
161
        super (Gst08Operation, self).start ()
139
162
        if self.running and not self.__use_threads:
140
 
                self.__source = gobject.idle_add (self.bin.iterate)
 
163
            self.__source = gobject.idle_add (self.bin.iterate)
141
164
 
142
165
    def stop (self):
143
166
        if self.__source is not None:
191
214
        try:
192
215
            total, format = self.query_element.query_duration (format)
193
216
            return float (total)
194
 
        except gst.QueryError, e:
 
217
        except gst.QueryError, err:
195
218
            return 0.0
196
219
 
197
220
    def query_position (self, format = gst.FORMAT_TIME):
249
272
    NEW_PAD_SIGNAL = "new-pad"
250
273
    GstOperation = Gst08Operation
251
274
 
 
275
def create_source(source, location, src_prop="location"):
 
276
    src = safe_element_factory_make(source)
 
277
    src.set_property(src_prop, location)
 
278
    return src
 
279
 
 
280
################################################################################
252
281
class AudioMetadataListener (operations.OperationListener):
253
282
    """
254
283
    The on_metadata event is called before the FinishedEvent, if the metadata
261
290
    "Event that holds the audio metadata."
262
291
    
263
292
    def __init__ (self, source, id, metadata):
264
 
        operations.FinishedEvent.__init__ (source, id)
 
293
        operations.Event.__init__ (source, id)
265
294
        self.__metadata = metadata
266
295
        
267
296
    metadata = property (lambda self: self.__metadata)
293
322
        self.__oper.query_element = self._fakesink
294
323
        self.__oper.listeners.append (self) 
295
324
        self.__metadata = {}
 
325
        self.__element = None
296
326
 
297
327
    def start (self):
298
328
        self.__oper.start ()
316
346
        self.__metadata.update (taglist)
317
347
 
318
348
    def on_finished (self, event):
 
349
        if event.id == operations.ERROR:
 
350
            self._propagate(event)
 
351
            return
 
352
            
319
353
        try:
320
354
            duration = int (self.__metadata["duration"]) / gst.SECOND
321
355
        except KeyError:
322
356
            duration = 0
 
357
        
 
358
        if duration == -1 or duration == 0:
 
359
            self._send_finished_event(operations.ERROR)
 
360
            return
 
361
            
323
362
        self.__metadata["duration"] = duration
324
363
        
325
364
        evt = operations.Event (self)
334
373
            self.__metadata["duration"] = \
335
374
                self.__oper.query_duration (gst.FORMAT_TIME)
336
375
 
337
 
def fileAudioMetadata (filename):
338
 
    """
339
 
    Returns the audio metadata from a file.
340
 
    """
341
 
    filesrc = gst.element_factory_make ("filesrc", "source")
342
 
    filesrc.set_property ("location", filename)
343
 
    return AudioMetadata(filesrc)
344
 
 
345
 
def gvfsAudioMetadata (uri):
346
 
    """
347
 
    Returns the audio metadata from an URI.
348
 
    """
349
 
    filesrc = gst.element_factory_make ("gnomevfssrc", "source")
350
 
    filesrc.set_property ("location", uri)
351
 
    return AudioMetadata(filesrc)
352
 
 
353
 
    
 
376
def get_metadata(source, location):
 
377
    return AudioMetadata(create_source(source, location))
 
378
 
 
379
 
354
380
################################################################################
355
381
WavPcmStruct = {
356
382
    'rate'      : 44100,
361
387
    'endianness': 1234
362
388
}
363
389
 
364
 
WavPcmParse = ("audio/x-raw-int, endianness=(int)1234, width=(int)16, "
 
390
_WAV_PCM_PARSE = ("audio/x-raw-int, endianness=(int)1234, width=(int)16, "
365
391
               "depth=(int)16, signed=(boolean)true, rate=(int)44100, "
366
392
               "channels=(int)2")
367
393
 
368
 
def capsIsWavPcm (caps):
369
 
    global WavPcmParse
370
 
    
 
394
def is_caps_wav_pcm (caps):
371
395
    struct = caps[0]
372
396
    if not struct.get_name () == "audio/x-raw-int":
373
397
        return False
388
412
    running = property (lambda self: self.oper.running)
389
413
 
390
414
    def __init__ (self, source):
 
415
        
391
416
        super (IsWavPcm, self).__init__ ()
392
 
    
 
417
        
 
418
        self.is_wav_pcm = False
393
419
        bin = gst.parse_launch (
394
420
            "typefind name=iwp_typefind ! \
395
421
            wavparse name=iwp_wavparse ! "
396
 
            + WavPcmParse +
 
422
            + _WAV_PCM_PARSE +
397
423
            " ! fakesink name=iwp_fakesink"
398
424
        )
399
425
        
407
433
        sink.set_property ("signal-handoffs", True)
408
434
        sink.connect ("handoff", self.on_handoff)
409
435
        
410
 
        waveparse = bin.get_by_name ("iwp_wavparse")
411
 
        waveparse.connect (NEW_PAD_SIGNAL, self.on_new_pad)
 
436
        self.waveparse = bin.get_by_name ("iwp_wavparse")
 
437
        self.waveparse.connect (NEW_PAD_SIGNAL, self.on_new_pad)
412
438
        
413
439
        self.oper.bin.add (source)
414
440
        source.link (decoder)
415
441
        
416
 
        self.isPcm = False
 
442
        self.is_wav_pcm = False
417
443
 
418
444
    def on_handoff (self, *args):
419
445
        self.oper.stop ()
420
446
    
421
447
    def on_new_pad (self, src, pad):
422
448
        caps = pad.get_caps()
423
 
        self.isWavPcm = capsIsWavPcm (caps)
424
 
 
 
449
        self.is_wav_pcm = is_caps_wav_pcm (caps)
 
450
    
425
451
    def on_finished (self, event):
426
 
        if event.id != operations.ERROR and self.isWavPcm:
427
 
            assert event.id == operations.SUCCESSFUL or event.id == operations.ABORTED
 
452
        if event.id != operations.ERROR and self.is_wav_pcm:
 
453
            assert event.id == operations.SUCCESSFUL or \
 
454
                   event.id == operations.ABORTED
428
455
            
429
456
            self._send_finished_event (operations.SUCCESSFUL)
430
457
        else:
448
475
    
449
476
    running = property (lambda self: self.__oper != None)
450
477
 
451
 
 
452
 
def fileIsPcmWav (filename):
453
 
    src = gst.element_factory_make ("filesrc")
454
 
    src.set_property ("location", filename)
455
 
    return IsWavPcm (src)
456
 
fileIsPcmWav = operations.async(fileIsPcmWav)
457
 
fileIsPcmWav = operations.operation_factory(fileIsPcmWav)
458
 
 
459
 
def gvfsIsPcmWav(uri):
460
 
    src = gst.element_factory_make("gnomevfssrc")
461
 
    src.set_property("location", uri)
462
 
    return IsWavPcm(src)
463
 
 
464
 
gvfsIsPcmWav = operations.async(gvfsIsPcmWav)
465
 
gvfsIsPcmWav = operations.operation_factory(gvfsIsPcmWav)
466
 
 
467
 
def sourceToWav (source, sink):
 
478
def is_wav_pcm(source, location):
 
479
    return IsWavPcm(create_source(source, location))
 
480
 
 
481
is_wav_pcm = operations.operation_factory(is_wav_pcm)
 
482
is_wav_pcm = operations.async(is_wav_pcm)
 
483
 
 
484
################################################################################
 
485
def source_to_wav(source, sink):
468
486
    """
469
487
    Converts a given source element to wav format and sends it to sink element.
470
488
    
471
489
    To convert a media file to a wav using gst-launch:
472
 
    source ! decodebin ! audioconvert ! audioscale !$WavPcmParse ! wavenc
 
490
    source ! decodebin ! audioconvert ! audioscale !$_WAV_PCM_PARSE ! wavenc
473
491
    """
 
492
 
474
493
    bin = gst.parse_launch (
475
494
        "decodebin name=stw_decodebin !"
476
495
        "audioconvert ! "
477
 
        + WavPcmParse +
 
496
        + _WAV_PCM_PARSE +
478
497
        " ! wavenc name=stw_wavenc"
479
498
    )
480
499
    oper = GstOperation(sink, bin)
489
508
    
490
509
    return oper
491
510
 
492
 
sourceToWav = operations.operation_factory(sourceToWav)
493
 
 
494
 
 
495
 
def fileToWav (src_filename, sink_filename):
 
511
source_to_wav = operations.operation_factory(source_to_wav)
 
512
 
 
513
def convert_to_wav(source, source_location, sink_location):
496
514
    """
497
515
    Utility function that given a source filename it converts it to a wav
498
516
    with sink_filename.
499
517
    """
500
 
    src = gst.element_factory_make ("filesrc")
501
 
    src.set_property ("location", src_filename)
502
 
    sink = gst.element_factory_make ("filesink")
503
 
    sink.set_property ("location", sink_filename)
504
 
    return sourceToWav (src, sink)
505
 
 
 
518
    sink = safe_element_factory_make("filesink")
 
519
    sink.set_property("location", sink_location)
 
520
    return source_to_wav(create_source(source, source_location), sink)
 
521
 
 
522
convert_to_wav = operations.operation_factory(convert_to_wav)
 
523
convert_to_wav = operations.async(convert_to_wav)
 
524
 
 
525
commands = {
 
526
    "convert": convert_to_wav,
 
527
    "is_wav": is_wav_pcm,
 
528
    "get_metadata": get_metadata
 
529
}
 
530
 
 
531
def parse_command(operation, source, source_location, *args):
 
532
    return commands[operation](source, source_location, *args)
 
533
    
506
534
################################################################################
507
535
 
508
536
################################################################################
509
537
if __name__ == '__main__':
510
538
    import sys
511
 
    
 
539
    import gst
 
540
 
512
541
    mainloop = gobject.MainLoop ()
513
 
    class L (GstOperationListener):
514
 
        def __init__(self, foo):
515
 
            self.foo = foo
 
542
    class Listener (GstOperationListener):
 
543
        def __init__(self, oper):
 
544
            self.oper = oper
516
545
            
517
546
        def on_metadata (self, event, metadata):
518
 
            print metadata
 
547
            print >> sys.stderr, metadata
519
548
            
520
549
        def on_finished (self, event):
521
 
            if event.id == operations.ABORTED:
522
 
                print "Aborted!"
523
 
                
524
 
            if event.id == operations.ERROR:
525
 
                print "Error:", event.error
526
 
            #gst.main_quit()
 
550
            self.success = operations.SUCCESSFUL == event.id
527
551
            mainloop.quit ()
528
552
 
529
553
        def on_progress (self):
530
 
            #print
531
 
            self.foo.progress
 
554
            print self.oper.progress
532
555
            return True
533
556
    
534
 
    #f = fileToWav (sys.argv[1], sys.argv[2])
535
 
    f = gvfsIsPcmWav (sys.argv[1])
536
 
    print operations.syncOperation (f).id == operations.SUCCESSFUL
537
 
    raise SystemError
538
 
    #f = fileAudioMetadata (sys.argv[1])
 
557
    #f = convert_to_wav (FILE_SRC, sys.argv[1], sys.argv[2])
 
558
    f = parse_command(sys.argv[1], FILE_SRC, sys.argv[2], *sys.argv[3:])
 
559
    #f = is_wav_pcm (FILE_SRC, sys.argv[1])
 
560
    #print operations.syncOperation (f).id == operations.SUCCESSFUL
 
561
    #raise SystemError
 
562
    #f = get_metadata("filesrc", sys.argv[1])
539
563
    #f = extractAudioTrackFile ("/dev/cdrom", int(sys.argv[1]) + 1, sys.argv[2])
540
 
    l = L(f)
541
 
    #gobject.timeout_add (200, l.on_progress)
 
564
    l = Listener(f)
 
565
    if isinstance(f, operations.MeasurableOperation):
 
566
        gobject.timeout_add (200, l.on_progress)
542
567
    f.listeners.append (l)
543
568
    f.start()
544
569
    l.finished = False
545
 
    #gst.main()
546
570
 
547
571
    mainloop.run ()
548
 
#    while not l.finished:
549
 
#        pass
 
572
    if not l.success:
 
573
        import sys
 
574
        sys.exit(1)
550
575