home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / python2.4 / site-packages / serpentine / audio.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2006-08-31  |  19.9 KB  |  581 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. '''
  5. This module contains operations to convert sound files to WAV and to
  6. retrieve a their metadata.
  7. '''
  8. if __name__ == '__main__':
  9.     
  10.     try:
  11.         import pygst
  12.         pygst.require('0.10')
  13.     except ImportError:
  14.         pass
  15.     except:
  16.         None<EXCEPTION MATCH>ImportError
  17.     
  18.  
  19. None<EXCEPTION MATCH>ImportError
  20. import threading
  21. import gst
  22. import gobject
  23. import operations
  24. GVFS_SRC = 'gnomevfssrc'
  25. FILE_SRC = 'filesrc'
  26.  
  27. class ElementNotFoundError(KeyError):
  28.     '''This error is thrown when an element is not found'''
  29.     pass
  30.  
  31. if gst.gst_version < (0, 9):
  32.     
  33.     def safe_element_factory_make(*args, **kwargs):
  34.         element = gst.element_factory_make(*args, **kwargs)
  35.         if element is None:
  36.             raise ElementNotFoundError(args)
  37.         
  38.         return element
  39.  
  40. else:
  41.     safe_element_factory_make = gst.element_factory_make
  42.  
  43. class GstPlayingFailledError(StandardError):
  44.     """This error is thrown when we can't set the state to PLAYING"""
  45.     pass
  46.  
  47.  
  48. class GstOperationListener(operations.OperationListener):
  49.     
  50.     def on_tag(self, event, tag):
  51.         '''Called when a tag is found'''
  52.         pass
  53.  
  54.     
  55.     def on_eos(self, event):
  56.         '''Called when the pipeline reaches EOS.'''
  57.         pass
  58.  
  59.     
  60.     def on_error(self, event, error):
  61.         '''Called when an error occurs'''
  62.         pass
  63.  
  64.  
  65.  
  66. class GstPipelineOperation(operations.MeasurableOperation):
  67.     '''GStreamer pipeline operation'''
  68.     can_start = property((lambda self: self._GstPipelineOperation__can_start))
  69.     running = property((lambda self: self._GstPipelineOperation__running))
  70.     bin = property((lambda self: self._GstPipelineOperation__bin))
  71.     query_element = None
  72.     progress = property((lambda self: self._get_progress()))
  73.     
  74.     def __init__(self, query_element, pipeline):
  75.         super(GstPipelineOperation, self).__init__()
  76.         self.query_element = query_element
  77.         self._GstPipelineOperation__bin = pipeline
  78.         self._GstPipelineOperation__progress = 0.0
  79.         self._GstPipelineOperation__can_start = True
  80.         self._GstPipelineOperation__running = False
  81.         self._GstPipelineOperation__duration = 0
  82.  
  83.     
  84.     def start(self):
  85.         if not self.can_start:
  86.             raise AssertionError
  87.         if self.bin.set_state(gst.STATE_PLAYING):
  88.             self._GstPipelineOperation__can_start = False
  89.             self._GstPipelineOperation__running = True
  90.         else:
  91.             raise GstPlayingFailledError()
  92.  
  93.     
  94.     def stop(self):
  95.         self._finalize(operations.ABORTED)
  96.  
  97.     
  98.     def query_duration(self, format = gst.FORMAT_BYTES):
  99.         '''Return the total duration'''
  100.         return 0.0
  101.  
  102.     
  103.     def query_position(self, format = gst.FORMAT_BYTES):
  104.         '''Return the current position'''
  105.         return 0
  106.  
  107.     
  108.     def _finalize(self, event_id, error = None):
  109.         if self._GstPipelineOperation__running:
  110.             self.bin.set_state(gst.STATE_NULL)
  111.             self._GstPipelineOperation__running = False
  112.             self._send_finished_event(event_id, error)
  113.         
  114.  
  115.     
  116.     def _get_progress(self):
  117.         if self.query_element and self._GstPipelineOperation__progress < 1:
  118.             if not self._GstPipelineOperation__duration:
  119.                 self._GstPipelineOperation__duration = self.query_duration()
  120.             
  121.             if self._GstPipelineOperation__duration == 0:
  122.                 progress = 0
  123.             else:
  124.                 position = self.query_position()
  125.                 progress = self.query_position() / self._GstPipelineOperation__duration
  126.             self._GstPipelineOperation__progress = max(self._GstPipelineOperation__progress, progress)
  127.             if self._GstPipelineOperation__progress <= self._GstPipelineOperation__progress:
  128.                 pass
  129.             elif not self._GstPipelineOperation__progress <= 1:
  130.                 raise AssertionError, self._GstPipelineOperation__progress
  131.         
  132.         return self._GstPipelineOperation__progress
  133.  
  134.     
  135.     def _on_eos(self):
  136.         event = operations.Event(self)
  137.         self._notify('on_eos', event)
  138.         self._finalize(operations.SUCCESSFUL)
  139.  
  140.     
  141.     def _on_error(self, error):
  142.         event = operations.Event(self)
  143.         self._notify('on_error', event, error)
  144.         self._finalize(operations.ERROR, error)
  145.  
  146.     
  147.     def _on_tag(self, taglist):
  148.         event = operations.Event(self)
  149.         self._notify('on_tag', event, taglist)
  150.  
  151.  
  152.  
  153. class Gst08Operation(GstPipelineOperation):
  154.     '''Implement GstPipelineOperation with gstreamer 0.8 API'''
  155.     
  156.     def __init__(self, query_element = None, pipeline = None, use_threads = False):
  157.         if pipeline is None:
  158.             if not use_threads or gst.Thread():
  159.                 pass
  160.             pipeline = gst.Pipeline()
  161.         
  162.         super(Gst08Operation, self).__init__(query_element, pipeline)
  163.         self._Gst08Operation__use_threads = use_threads
  164.         pipeline.connect('found-tag', self._on_tag)
  165.         pipeline.connect('error', self._on_error)
  166.         pipeline.connect('eos', self._on_eos)
  167.         self._Gst08Operation__source = None
  168.  
  169.     
  170.     def start(self):
  171.         super(Gst08Operation, self).start()
  172.         if self.running and not (self._Gst08Operation__use_threads):
  173.             self._Gst08Operation__source = gobject.idle_add(self.bin.iterate)
  174.         
  175.  
  176.     
  177.     def stop(self):
  178.         if self._Gst08Operation__source is not None:
  179.             gobject.source_remove(self._Gst08Operation__source)
  180.             self._Gst08Operation__source = None
  181.         
  182.         super(Gst08Operation, self).stop()
  183.  
  184.     
  185.     def query_duration(self, format = gst.FORMAT_TIME):
  186.         return float(self.query_element.query(gst.QUERY_TOTAL, format))
  187.  
  188.     
  189.     def query_position(self, format = gst.FORMAT_TIME):
  190.         return self.query_element.query(gst.QUERY_POSITION, format)
  191.  
  192.     
  193.     def _on_error(self, pipeline, element, error, user_data = None):
  194.         super(Gst08Operation, self)._on_error(error)
  195.  
  196.     
  197.     def _on_tag(self, pipeline, element, taglist):
  198.         super(Gst08Operation, self)._on_tag(taglist)
  199.  
  200.     
  201.     def _on_eos(self, pipeline):
  202.         super(Gst08Operation, self)._on_eos()
  203.  
  204.     
  205.     def _finalize(self, event_id, error = None):
  206.         super(Gst08Operation, self)._finalize(event_id, error)
  207.         if self._Gst08Operation__source is not None:
  208.             gobject.source_remove(self._Gst08Operation__source)
  209.             self._Gst08Operation__source = None
  210.         
  211.  
  212.  
  213.  
  214. class Gst09Operation(GstPipelineOperation):
  215.     '''Implement GstPipelineOperation with gstreamer 0.9/0.10 API'''
  216.     running = property((lambda self: self._Gst09Operation__running))
  217.     
  218.     def __init__(self, query_element = None, pipeline = None):
  219.         if pipeline is None:
  220.             pipeline = gst.Pipeline()
  221.         
  222.         super(Gst09Operation, self).__init__(query_element, pipeline)
  223.         self.bus = pipeline.get_bus()
  224.         self.bus.add_watch(self._dispatch_bus_message)
  225.         self._Gst09Operation__running = False
  226.         self.lock = threading.RLock()
  227.  
  228.     
  229.     def query_duration(self, format = gst.FORMAT_TIME):
  230.         
  231.         try:
  232.             (total, format) = self.query_element.query_duration(format)
  233.             return float(total)
  234.         except gst.QueryError:
  235.             err = None
  236.             return 0.0
  237.  
  238.  
  239.     
  240.     def query_position(self, format = gst.FORMAT_TIME):
  241.         
  242.         try:
  243.             (pos, format) = self.query_element.query_position(format)
  244.             return pos
  245.         except gst.QueryError:
  246.             return 0
  247.  
  248.  
  249.     
  250.     def start(self):
  251.         self.lock.acquire()
  252.         
  253.         try:
  254.             if not self._Gst09Operation__running:
  255.                 self._Gst09Operation__running = True
  256.                 super(Gst09Operation, self).start()
  257.         finally:
  258.             self.lock.release()
  259.  
  260.  
  261.     
  262.     def _dispatch_bus_message(self, bus, message):
  263.         handler = getattr(self, '_on_' + message.type.first_value_nick, None)
  264.         if handler:
  265.             handler(bus, message)
  266.         
  267.         return True
  268.  
  269.     
  270.     def _finalize(self, event_id, error = None):
  271.         self.lock.acquire()
  272.         
  273.         try:
  274.             if self.running:
  275.                 self._Gst09Operation__running = False
  276.                 
  277.                 def wrapper():
  278.                     super(Gst09Operation, self)._finalize(event_id, error)
  279.                     return False
  280.  
  281.                 gobject.idle_add(wrapper)
  282.         finally:
  283.             self.lock.release()
  284.  
  285.  
  286.     
  287.     def _on_eos(self, bus, message):
  288.         super(Gst09Operation, self)._on_eos()
  289.  
  290.     
  291.     def _on_error(self, bus, message):
  292.         super(Gst09Operation, self)._on_error(message.parse_error())
  293.  
  294.     
  295.     def _on_tag(self, bus, message):
  296.         super(Gst09Operation, self)._on_tag(message.parse_tag())
  297.  
  298.  
  299. if gst.gst_version[0] == 0 and gst.gst_version[1] >= 9:
  300.     NEW_PAD_SIGNAL = 'pad-added'
  301.     GstOperation = Gst09Operation
  302. else:
  303.     NEW_PAD_SIGNAL = 'new-pad'
  304.     GstOperation = Gst08Operation
  305.  
  306. def create_source(source, location, src_prop = 'location'):
  307.     src = safe_element_factory_make(source)
  308.     src.set_property(src_prop, location)
  309.     return src
  310.  
  311.  
  312. class AudioMetadataListener(operations.OperationListener):
  313.     '''
  314.     The on_metadata event is called before the FinishedEvent, if the metadata
  315.     retriavel is successful.
  316.     '''
  317.     
  318.     def on_metadata(self, event, metadata):
  319.         pass
  320.  
  321.  
  322.  
  323. class AudioMetadataEvent(operations.Event):
  324.     '''Event that holds the audio metadata.'''
  325.     
  326.     def __init__(self, source, id, metadata):
  327.         operations.Event.__init__(source, id)
  328.         self._AudioMetadataEvent__metadata = metadata
  329.  
  330.     metadata = property((lambda self: self._AudioMetadataEvent__metadata))
  331.  
  332.  
  333. class AudioMetadata(operations.Operation, GstOperationListener):
  334.     '''Returns the metadata associated with the source element.
  335.     
  336.     To retrieve the metadata associated with a certain media file on gst-launch -t:
  337.     source ! decodebin ! fakesink
  338.     '''
  339.     can_start = property((lambda self: self._AudioMetadata__oper.can_start))
  340.     running = property((lambda self: self._AudioMetadata__oper.running))
  341.     
  342.     def __init__(self, source):
  343.         super(AudioMetadata, self).__init__()
  344.         bin = gst.parse_launch('decodebin name=am_decodebin !                                 fakesink name=am_fakesink')
  345.         self._AudioMetadata__oper = GstOperation(pipeline = bin)
  346.         bin.add(source)
  347.         source.link(bin.get_by_name('am_decodebin'))
  348.         self._fakesink = bin.get_by_name('am_fakesink')
  349.         self._fakesink.set_property('signal-handoffs', True)
  350.         self._fakesink.connect('handoff', self.on_handoff)
  351.         self._AudioMetadata__oper.query_element = self._fakesink
  352.         self._AudioMetadata__oper.listeners.append(self)
  353.         self._AudioMetadata__metadata = { }
  354.         self._AudioMetadata__element = None
  355.  
  356.     
  357.     def start(self):
  358.         self._AudioMetadata__oper.start()
  359.  
  360.     
  361.     def stop(self):
  362.         self._check_duration()
  363.         self._AudioMetadata__oper.stop()
  364.  
  365.     
  366.     def on_eos(self, event):
  367.         self._check_duration()
  368.  
  369.     
  370.     def on_error(self, event, message):
  371.         self._check_duration()
  372.  
  373.     
  374.     def on_handoff(self, *ignored):
  375.         self._fakesink.set_property('signal-handoffs', False)
  376.         self.stop()
  377.  
  378.     
  379.     def on_tag(self, event, taglist):
  380.         self._AudioMetadata__metadata.update(taglist)
  381.  
  382.     
  383.     def on_finished(self, event):
  384.         if event.id == operations.ERROR:
  385.             self._propagate(event)
  386.             return None
  387.         
  388.         
  389.         try:
  390.             duration = int(self._AudioMetadata__metadata['duration']) / gst.SECOND
  391.         except KeyError:
  392.             duration = 0
  393.  
  394.         if duration == -1 or duration == 0:
  395.             self._send_finished_event(operations.ERROR)
  396.             return None
  397.         
  398.         self._AudioMetadata__metadata['duration'] = duration
  399.         evt = operations.Event(self)
  400.         self._notify('on_metadata', evt, self._AudioMetadata__metadata)
  401.         self._AudioMetadata__metadata = None
  402.         self._AudioMetadata__element = None
  403.         self._send_finished_event(operations.SUCCESSFUL)
  404.  
  405.     
  406.     def _check_duration(self):
  407.         if not self._AudioMetadata__metadata.has_key('duration'):
  408.             self._AudioMetadata__metadata['duration'] = self._AudioMetadata__oper.query_duration(gst.FORMAT_TIME)
  409.         
  410.  
  411.  
  412.  
  413. def get_metadata(source, location):
  414.     return AudioMetadata(create_source(source, location))
  415.  
  416. WavPcmStruct = {
  417.     'rate': 44100,
  418.     'signed': True,
  419.     'channels': 2,
  420.     'width': 16,
  421.     'depth': 16,
  422.     'endianness': 1234 }
  423. _WAV_PCM_PARSE = 'audio/x-raw-int, endianness=(int)1234, width=(int)16, depth=(int)16, signed=(boolean)true, rate=(int)44100, channels=(int)2'
  424.  
  425. def is_caps_wav_pcm(caps):
  426.     struct = caps[0]
  427.     if not struct.get_name() == 'audio/x-raw-int':
  428.         return False
  429.     
  430.     for key, value in WavPcmStruct.iteritems():
  431.         if not struct.has_field(key) or struct[key] != value:
  432.             return False
  433.             continue
  434.     
  435.     return True
  436.  
  437.  
  438. class IsWavPcm(operations.Operation, GstOperationListener):
  439.     '''
  440.     Tests if a certain WAV is in the PCM format.
  441.     '''
  442.     can_start = property((lambda self: self.oper.can_start))
  443.     running = property((lambda self: self.oper.running))
  444.     
  445.     def __init__(self, source):
  446.         super(IsWavPcm, self).__init__()
  447.         self.is_wav_pcm = False
  448.         bin = gst.parse_launch('typefind name=iwp_typefind !             wavparse name=iwp_wavparse ! ' + _WAV_PCM_PARSE + ' ! fakesink name=iwp_fakesink')
  449.         self.oper = GstOperation(pipeline = bin)
  450.         self.oper.listeners.append(self)
  451.         decoder = bin.get_by_name('iwp_typefind')
  452.         sink = bin.get_by_name('iwp_fakesink')
  453.         self.oper.query_element = sink
  454.         sink.set_property('signal-handoffs', True)
  455.         sink.connect('handoff', self.on_handoff)
  456.         self.waveparse = bin.get_by_name('iwp_wavparse')
  457.         self.waveparse.connect(NEW_PAD_SIGNAL, self.on_new_pad)
  458.         self.oper.bin.add(source)
  459.         source.link(decoder)
  460.         self.is_wav_pcm = False
  461.  
  462.     
  463.     def on_handoff(self, *args):
  464.         self.oper.stop()
  465.  
  466.     
  467.     def on_new_pad(self, src, pad):
  468.         caps = pad.get_caps()
  469.         self.is_wav_pcm = is_caps_wav_pcm(caps)
  470.  
  471.     
  472.     def on_finished(self, event):
  473.         if event.id != operations.ERROR and self.is_wav_pcm:
  474.             if not event.id == operations.SUCCESSFUL and event.id == operations.ABORTED:
  475.                 raise AssertionError
  476.             self._send_finished_event(operations.SUCCESSFUL)
  477.         elif event.id == operations.SUCCESSFUL:
  478.             eid = operations.ERROR
  479.             err = StandardError('Not a valid WAV PCM')
  480.         else:
  481.             eid = event.id
  482.             err = event.error
  483.         self._send_finished_event(eid, err)
  484.  
  485.     
  486.     def start(self):
  487.         self.oper.start()
  488.         self._IsWavPcm__can_start = False
  489.  
  490.     
  491.     def stop(self):
  492.         self.oper.stop()
  493.  
  494.     can_start = property((lambda self: self._IsWavPcm__can_start))
  495.     running = property((lambda self: self._IsWavPcm__oper != None))
  496.  
  497.  
  498. def is_wav_pcm(source, location):
  499.     return IsWavPcm(create_source(source, location))
  500.  
  501. is_wav_pcm = operations.operation_factory(is_wav_pcm)
  502. is_wav_pcm = operations.async(is_wav_pcm)
  503.  
  504. def source_to_wav(source, sink):
  505.     '''
  506.     Converts a given source element to wav format and sends it to sink element.
  507.     
  508.     To convert a media file to a wav using gst-launch:
  509.     source ! decodebin ! audioconvert ! audioscale !$_WAV_PCM_PARSE ! wavenc
  510.     '''
  511.     bin = gst.parse_launch('decodebin name=stw_decodebin !audioconvert ! ' + _WAV_PCM_PARSE + ' ! wavenc name=stw_wavenc')
  512.     oper = GstOperation(sink, bin)
  513.     decoder = bin.get_by_name('stw_decodebin')
  514.     encoder = bin.get_by_name('stw_wavenc')
  515.     oper.bin.add(source)
  516.     oper.bin.add(sink)
  517.     source.link(decoder)
  518.     encoder.link(sink)
  519.     return oper
  520.  
  521. source_to_wav = operations.operation_factory(source_to_wav)
  522.  
  523. def convert_to_wav(source, source_location, sink_location):
  524.     '''
  525.     Utility function that given a source filename it converts it to a wav
  526.     with sink_filename.
  527.     '''
  528.     sink = safe_element_factory_make('filesink')
  529.     sink.set_property('location', sink_location)
  530.     return source_to_wav(create_source(source, source_location), sink)
  531.  
  532. convert_to_wav = operations.operation_factory(convert_to_wav)
  533. convert_to_wav = operations.async(convert_to_wav)
  534. commands = {
  535.     'convert': convert_to_wav,
  536.     'is_wav': is_wav_pcm,
  537.     'get_metadata': get_metadata }
  538.  
  539. def parse_command(operation, source, source_location, *args):
  540.     return commands[operation](source, source_location, *args)
  541.  
  542. if __name__ == '__main__':
  543.     import sys
  544.     import gst
  545.     mainloop = gobject.MainLoop()
  546.     
  547.     class Listener(GstOperationListener):
  548.         
  549.         def __init__(self, oper):
  550.             self.oper = oper
  551.  
  552.         
  553.         def on_metadata(self, event, metadata):
  554.             print >>sys.stderr, metadata
  555.  
  556.         
  557.         def on_finished(self, event):
  558.             self.success = operations.SUCCESSFUL == event.id
  559.             mainloop.quit()
  560.  
  561.         
  562.         def on_progress(self):
  563.             print self.oper.progress
  564.             return True
  565.  
  566.  
  567.     f = parse_command(sys.argv[1], FILE_SRC, sys.argv[2], *sys.argv[3:])
  568.     l = Listener(f)
  569.     if isinstance(f, operations.MeasurableOperation):
  570.         gobject.timeout_add(200, l.on_progress)
  571.     
  572.     f.listeners.append(l)
  573.     f.start()
  574.     l.finished = False
  575.     mainloop.run()
  576.     if not l.success:
  577.         import sys
  578.         sys.exit(1)
  579.     
  580.  
  581.