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.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2006-08-31  |  19.8 KB  |  573 lines

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