def _setup_pipeline(self, fpath): fpathnz = fpath.replace(' ', '_') gst.debug('_setup_pipeline: %r' % (fpath,)) self.ppl = gst.Pipeline('D-%s' % fpathnz) src = gst.element_make_from_uri(gst.URI_SRC, fpath, 'src-%s' % fpathnz) if not src: gst.warning('No element to access: %r' % fpath) self._finish(AnalysisError('No element to access the URI.')) return False dbin = gst.element_factory_make('decodebin2', 'dbin') self._connect(dbin, 'new-decoded-pad', self._cb_new_decoded_pad) self._connect(dbin, 'no-more-pads', self._cb_no_more_pads) self._connect(dbin, 'unknown-type', self._cb_unknown_type) tfind = dbin.get_by_name('typefind') self._connect(tfind, 'have-type', self._cb_have_type) self._connect(tfind.get_pad('src'), 'notify::caps', self._cb_notify_caps_tfind) self.ppl.add(src, dbin) src.link(dbin) gst.debug('pipeline created') self.bus = self.ppl.get_bus() self._connect(self.bus, 'message', self._cb_bus_message) self.bus.add_signal_watch() return True
def getInstallableCodecsUbuntu(): import warnings warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) import apt codecs = [] try: apt_cache = apt.Cache() except: gst.warning('Failed to read APT cache') return [] #import time #now = time.time() for pkg in apt_cache: # check only packages that are releated to gstreamer # this is a performance hack that brings this code from 30s # to 1s on cold cache if (not "gstreamer" in pkg.name or pkg.isInstalled or not pkg.candidateDownloadable): continue record = pkg.candidateRecord if not record: continue if not record.has_key("Gstreamer-Version"): continue if record.has_key("Gstreamer-Decoders"): codec_list = record["Gstreamer-Decoders"].split(";") codecs.extend([item.split(",")[0].strip() for item in codec_list]) #print time.time() - now return codecs
def _dataProbeCb(self, pad, data): if isinstance(data, gst.Buffer): gst.warning("Saw buffer %s (dur:%s) => %s" % (gst.TIME_ARGS(data.timestamp), gst.TIME_ARGS(data.duration), gst.TIME_ARGS(data.timestamp+data.duration))) self._lastBuffer = data return GnlFileSourceTest._dataProbeCb(self, pad, data)
def timeout_cb(self): """ Callback for timeout, used in case tag messages do not include all the information required by self.req_keys. """ gst.warning('Timed out before getting tag for %s' % self.pbin.get_property('uri')) self.quit() return False
def queue_del(self,uri=None,pos=-1): """Remove an item from the queue. Item can be selected either by URI or by pos (position) in the queue. Removing the currently playing element will not stop playback. """ ans = [200] ind = -1 if uri: try: elem = self.queue_item_by_uri(uri) self.queue.index(elem) self.queue.remove(uri) ans.append('Removed element %s' % uri) except (ValueError, StopIteration) as e: err_msg = 'Exception:%s' % e.__str__() gst.warning(err_msg) ans = [400] ans.append(err_msg) elif pos >= 0: try: ind = pos del self.queue[pos] ans.append('Removed element at queue[%d]' % pos) except IndexError as e: err_msg = 'Failed to remove at %d. Exception:%s' % (pos,e.__str__()) gst.warning(err_msg) ans = [400] ans.append(err_msg) try: if ans[0] == 200: if ind < self.queue_pos: # update queue_pos to new queue size self.queue_pos -= 1 elif ind == self.queue_pos: # check if currently selected item was deleted if not ind and self.queue: # special case, first element was removed and # more are left, set queue_pos to head self.queue_pos = 0 if self.queue_pos >= 0: uri_new = self.queue[self.queue_pos]['uri'] get.debug('setting uri to %s' % uri_new) self.player.set_location(uri_new) else: # queue is empty now self.player.set_location(None) except Exception as e: print e err_msg = 'Problem near update queue_pos. Exception:%s' % e.__str__() gst.error(err_msg) ans = [400] ans.append(err_msg) if ans[0] == 200 and len(ans) > 1: # call to get debug output self.queue_get() return ans
def _notify_caps_cb(self, pad, args): caps = pad.get_negotiated_caps() if not caps: pad.info("no negotiated caps available") return pad.info("caps:%s" % caps.to_string()) # the caps are fixed # We now get the total length of that stream q = gst.query_new_duration(gst.FORMAT_TIME) pad.info("sending position query") if pad.get_peer().query(q): format, length = q.parse_duration() pad.info("got position query answer : %d:%d" % (length, format)) else: length = -1 gst.warning("position query didn't work") # We store the caps and length in the proper location if "audio" in caps.to_string(): self.audiocaps = caps self.audiolength = length try: pos = 0 cap = caps[pos] while not cap.has_key("rate"): pos += 1 cap = caps[pos] self.audiorate = cap["rate"] self.audiowidth = cap["width"] self.audiochannels = cap["channels"] except IndexError: pass if "x-raw-float" in caps.to_string(): self.audiofloat = True else: self.audiodepth = caps[0]["depth"] if self._nomorepads and ((not self.is_video) or self.videocaps): _log.debug("called @1") self._finished(True) elif "video" in caps.to_string(): self.videocaps = caps self.videolength = length try: pos = 0 cap = caps[pos] while not cap.has_key("width"): pos += 1 cap = caps[pos] self.videowidth = cap["width"] self.videoheight = cap["height"] self.videorate = cap["framerate"] except IndexError: pass if self._nomorepads and ((not self.is_audio) or self.audiocaps): _log.debug("called @2") self._finished(True)
def _notify_caps_cb(self, pad, args): caps = pad.get_negotiated_caps() if not caps: pad.info("no negotiated caps available") return pad.info("caps:%s" % caps.to_string()) # the caps are fixed # We now get the total length of that stream q = gst.query_new_duration(gst.FORMAT_TIME) pad.info("sending position query") if pad.get_peer().query(q): format, length = q.parse_duration() pad.info("got position query answer : %d:%d" % (length, format)) else: length = -1 gst.warning("position query didn't work") # We store the caps and length in the proper location if "audio" in caps.to_string(): self.audiocaps = caps self.audiolength = length try: pos = 0 cap = caps[pos] while not cap.has_key("rate"): pos += 1 cap = caps[pos] self.audiorate = cap["rate"] self.audiowidth = cap["width"] self.audiochannels = cap["channels"] except IndexError: pass if "x-raw-float" in caps.to_string(): self.audiofloat = True else: self.audiodepth = caps[0]["depth"] if self._nomorepads and ((not self.is_video) or self.videocaps): self._finished(True) elif "video" in caps.to_string(): self.videocaps = caps self.videolength = length try: pos = 0 cap = caps[pos] while not cap.has_key("width"): pos += 1 cap = caps[pos] self.videowidth = cap["width"] self.videoheight = cap["height"] self.videorate = cap["framerate"] except IndexError: pass if self._nomorepads and ((not self.is_audio) or self.audiocaps): self._finished(True)
def on_sync_message(self, bus, message): if message.structure is None: return message_name = message.structure.get_name() if message_name == 'prepare-xwindow-id': # Assign the viewport imagesink = message.src imagesink.set_property('force-aspect-ratio', True) try: imagesink.set_xwindow_id(self.draw_window.window.xid) except: gst.warning("Couldn't set the XID on our video sink !")
def remoteTest(self): # kickstart pipeline to initial state PythonDBusTest.remoteTest(self) debug("Setting pipeline to initial state %r", self.__pipeline_initial_state__) gst.log("Setting pipeline to initial state %r" % self.__pipeline_initial_state__) res = self.pipeline.set_state(self.__pipeline_initial_state__) debug("set_state returned %r", res) gst.log("set_state() returned %r" % res) self.validateStep("pipeline-change-state", not res == gst.STATE_CHANGE_FAILURE) if res == gst.STATE_CHANGE_FAILURE: warning("Setting pipeline to initial state failed, stopping test") gst.warning("State change failed, stopping") self.stop()
def on_message(self, bus, message): t = message.type if t == gst.MESSAGE_ERROR: err, debug = message.parse_error() print "Error: %s" % err, debug self.stop() elif t == gst.MESSAGE_EOS: gst.info("File playback completed") ok,moved = self.cb_eos() if ok: gst.debug('eos callback completed, moved queue %d places' % moved) else: gst.warning('eos callback failed!')
def switch(self, padname): switch = self.pipeline.get_by_name('s') stop_time = switch.emit('block') newpad = switch.get_static_pad(padname) start_time = newpad.get_property('running-time') gst.warning('stop time = %d' % (stop_time,)) gst.warning('stop time = %s' % (gst.TIME_ARGS(stop_time),)) gst.warning('start time = %d' % (start_time,)) gst.warning('start time = %s' % (gst.TIME_ARGS(start_time),)) gst.warning('switching from %r to %r' % (switch.get_property('active-pad'), padname)) switch.emit('switch', newpad, stop_time, start_time)
def _padElement(self, pad, direction): if not pad: gst.warning("GStreamer internal behavior changed, " + "cannot properly crawl the pipline") return None if isinstance(pad, gst.GhostPad): return self._padElement(pad.get_target(), direction) if pad.get_direction() == direction: return self._padElement(pad.get_peer(), direction) parent = pad.get_parent() if parent == None: gst.warning("GStreamer internal behavior changed, " + "cannot properly crawl the pipline") return None if isinstance(parent, gst.GhostPad): return self._padElement(parent.get_peer(), direction) return parent
def _notify_caps_cb(self, pad, args): self.discovered_cond.acquire() caps = pad.get_negotiated_caps() if not caps: pad.info("no negotiated caps available") self.discovered = True self.discovered_cond.notify() self.discovered_cond.release() return # the caps are fixed # We now get the total length of that stream q = gst.query_new_duration(gst.FORMAT_TIME) pad.info("sending duration query") if pad.get_peer().query(q): format, length = q.parse_duration() if format == gst.FORMAT_TIME: pad.info("got duration (time) : %s" % (gst.TIME_ARGS(length),)) else: pad.info("got duration : %d [format:%d]" % (length, format)) else: length = -1 gst.warning("duration query failed") # We store the caps and length in the proper location if "audio" in caps.to_string(): self.input_samplerate = caps[0]["rate"] if not self.output_samplerate: self.output_samplerate = self.input_samplerate self.input_channels = caps[0]["channels"] if not self.output_channels: self.output_channels = self.input_channels self.input_duration = length / gst.SECOND self.input_totalframes = int( self.input_duration * self.input_samplerate) if "x-raw-float" in caps.to_string(): self.input_width = caps[0]["width"] else: self.input_width = caps[0]["depth"] self.discovered = True self.discovered_cond.notify() self.discovered_cond.release()
def _notify_caps_cb(self, pad, args): caps = pad.get_negotiated_caps() if not caps: pad.info("no negotiated caps available") return pad.info("caps:%s" % caps.to_string()) # the caps are fixed # We now get the total length of that stream q = gst.query_new_duration(gst.FORMAT_TIME) pad.info("sending duration query") if pad.get_peer().query(q): format, length = q.parse_duration() if format == gst.FORMAT_TIME: pad.info("got duration (time) : %s" % (gst.TIME_ARGS(length), )) else: pad.info("got duration : %d [format:%d]" % (length, format)) else: length = -1 gst.warning("duration query failed") # We store the caps and length in the proper location if "audio" in caps.to_string(): self.audiocaps = caps self.audiolength = length self.audiorate = caps[0]["rate"] self.audiowidth = caps[0]["width"] self.audiochannels = caps[0]["channels"] if "x-raw-float" in caps.to_string(): self.audiofloat = True else: self.audiodepth = caps[0]["depth"] if self._nomorepads and ((not self.is_video) or self.videocaps): self._finished(True) elif "video" in caps.to_string(): self.videocaps = caps self.videolength = length self.videowidth = caps[0]["width"] self.videoheight = caps[0]["height"] self.videorate = caps[0]["framerate"] if self._nomorepads and ((not self.is_audio) or self.audiocaps): self._finished(True)
def _notify_caps_cb(self, pad, args): caps = pad.get_negotiated_caps() if not caps: pad.info("no negotiated caps available") return pad.info("caps:%s" % caps.to_string()) # the caps are fixed # We now get the total length of that stream q = gst.query_new_duration(gst.FORMAT_TIME) pad.info("sending duration query") if pad.get_peer().query(q): format, length = q.parse_duration() if format == gst.FORMAT_TIME: pad.info("got duration (time) : %s" % (gst.TIME_ARGS(length),)) else: pad.info("got duration : %d [format:%d]" % (length, format)) else: length = -1 gst.warning("duration query failed") # We store the caps and length in the proper location if "audio" in caps.to_string(): self.audiocaps = caps self.audiolength = length self.audiorate = caps[0]["rate"] self.audiowidth = caps[0]["width"] self.audiochannels = caps[0]["channels"] if "x-raw-float" in caps.to_string(): self.audiofloat = True else: self.audiodepth = caps[0]["depth"] if self._nomorepads and ((not self.is_video) or self.videocaps): self._finished(True) elif "video" in caps.to_string(): self.videocaps = caps self.videolength = length self.videowidth = caps[0]["width"] self.videoheight = caps[0]["height"] self.videorate = caps[0]["framerate"] if self._nomorepads and ((not self.is_audio) or self.audiocaps): self._finished(True)
def get_peak_dB(self, channel=None): """ Get the list of peak values for the given channel, in dB. If no channel specified, take peak over all channels. @param channel: channel number to get peak values for, starting from 0 @type channel: int or None @returns: the peak level graph in dB @rtype: L{level.Level} """ if channel is not None: return self.peakdBs[channel] peak = level.Level(scale=level.SCALE_DECIBEL) for i, (endtime, v) in enumerate(self.peakdBs[0]): maxdB = max([l[i][1] for l in self.peakdBs]) if maxdB > 0.0: gst.warning('maxdB higher than unity: %r dB' % maxdB) peak.append((endtime, maxdB)) return peak
def handle_cmd(self, msg): """ Receives a msg and executes it if it corresponds to a registered cmd Return values: - If successful: [200,data_returned_by_cmd] - else: [err_code,err_msg] """ if self.src == 'zmq': cmd,cmd_code,args = shared.json_server_dec(msg) gst.debug('dec: cmd_name=%s,'\ 'cmd_code=%d,args=%s' % (cmd,cmd_code,args.__str__())) else: words = msg.split() cmd = words[0] cmd_code = words[-1] args = [] cmd_code_dic= 0 ans = [200] # default to OK if not self.is_registered(cmd) or (self.src == 'stdin' and len(words) < 2): gst.error("Error: Invalid command: %s, Ignoring...\n" % cmd) help_msg = self.help_msg() if(self.src == 'stdin'): print help_msg ans = [401] ans.append(help_msg) else: # first arg is command name, last is cmd if if self.src == 'stdin': # if src is zmq, then json_server_dec() took # care of fetching arguments for command args = words[1:-1] try: # convert from string to int cmd_code = int(cmd_code) except ValueError as e: gst.warning('int(cmd_code) failed!Exception:%s' % e.__str__()) try: # get command id from dict, compare with rx id (must match) gst.debug('Matching command id with dict values...') cmd_code_dic = shared.cmd_name_id[cmd] try: # check matching if cmd_code_dic != cmd_code: gst.error('Command code received %d does not match dict %d' % (cmd_code,cmd_code_dic)) else: gst.debug('Command id matched!') try: if(args): gst.debug('Executing cmd=%s with args=%s' % (cmd,args)) args = args[0] if cmd == 'queue_add': ans = list(self.queue_add(args)) elif cmd == 'queue_del': param = -1 try: param = int(args) except ValueError as e: gst.debug('Param is not int. Exception:%s' % e.__str__()) if not param == -1: ans = list(self.queue_del(pos=param)) else: ans = list(self.queue_del(uri=args)) #TODO implement generic multi arg command and support for multi load (queue) # ans = self.fire(cmd,args) else: gst.debug('Executing cmd=%s without args' % cmd) ans = list(self.fire(cmd)) except ValueError as ve: print 'Exception:',ve except Exception, e: print 'Exception:',e gst.error('Problem near cmd execution: %s' % msg) ans = [402] except Exception as e: print 'Exception:',e gst.error('Problem near command id matching: (rx,dict)=(%d,%d)' % (cmd_code,cmd_code_dic)) except Exception as e: print 'Exception:',e gst.error('Problem near: find Id for cmd: %s' % cmd) # Take cmd result and prepare answer to send to client gst.debug('ans(len=%d)=%s' % (len(ans),ans)) assert(len(ans) == 1 or len(ans) == 2) # (code, data) data = [] if len(ans) == 2: data = ans[1] return shared.json_server_enc(cmd_code, ans[0], data)
def queue_add(self, location): """ Adds location to the play queue. NOTES: - location must be a valid URI - If self.verify_on_load==True, then location can be a directory. All .mp3 files from the directory will be loaded. Return values: - If successful: [200] - else: [err_code,[err_msg]]. """ ans = [200] is_dir = False is_ascii = True # ignore non-ascii stuff try: unicode(location) except UnicodeDecodeError as e: is_ascii = False gst.warning('Ignoring %s, not ascii' % location) ans = [406] ans.append(e.__str__()) if not is_ascii or not gst.uri_is_valid(location): if is_ascii: gst.error("Error: Invalid URI: %s\nExpected uri" "like file:///home/foo/bar.mp3\nIgnoring...\n" % location) ans = [403] else: # if(self.player.status()): # self.queued = True gst.debug('URI is valid: %s' % location) err_msg = [] code = 0 msg = '' if self.verify_on_load: gst.debug('Attempting to verify %s' % location) if location[0:4] == 'file': path = location[7:] try: with open(path) as f: pass except IOError as e: if e.errno == 21: is_dir = True loaded = [] try: # is directory, load content os.chdir(path) for f in os.listdir('.'): if f.endswith('.mp3'): full_path = location+'/'+f res = self.queue_add(full_path) if res[0] == 200: loaded.append(full_path) ans.append(loaded) except IOError as e: err_msg = 'Error parsing directory, will'\ 'stop loading, exception:%s' % e.__str__() gst.error(err_msg) ans = [404] ans.append(err_msg) else: err_msg = 'Will not load, exception when opening'\ '%s: %s' % (path,e.__str__()) gst.error(err_msg) ans = [404] ans.append(err_msg) elif location[0:4] == 'http': try: urlopen_ans = urlopen(location) code = urlopen_ans.code msg = urlopen_ans.msg if code >= 400: err_msg = 'urlopen failed with %d: %s' % (code,msg) except: err_msg = 'urlopen() failed' if err_msg: ans = [400] ans.append(err_msg) if not err_msg: gst.debug('Verification succeeded!') if err_msg: gst.warning(err_msg) elif not is_dir: gst.debug('Setting location to %s' % location) try: if location in self.queue: gst.info('Duplicate entry %s' % location) self.queue.append({'uri':location,'tags':{}}) try: gst.debug('will prepare tag getter: get_tags(%s)' % location) tgt = threading.Thread(target=tagget.get_tags, args=[self.queue[-1]['tags'], location]) gst.debug('will start tag getter') tgt.start() except Exception as e: err_msg = 'Problem near tag get thread. Exception:%s' % e.__str__() gst.warning(err_msg) # call to print current queue self.queue_get() if self.queue_pos == -1: gst.debug('New queue, will next()') ans_n = self.queue_next() if ans_n[0] == 200: gst.debug('New queue play success!') else: ans = [400] ans.append('Failed to set initial queue position') except Exception as e: print e ans = [400] gst.error('Problem near queue.append()') return ans
def _eos_cb(self, source): gst.debug("eos, start calcing") # get the highest peak RMS for this track highestdB = self._peaksdB[0][1] for (time, peakdB) in self._peaksdB: if peakdB > highestdB: highestdB = peakdB gst.debug("highest peak(dB): %f" % highestdB) # get the length (self.length, peakdB) = self._peaksdB[-1] # find the mix in point for (time, peakdB) in self._peaksdB: gst.log("time %s, peakdB %f" % (gst.TIME_ARGS(time), peakdB)) if peakdB > self._thresholddB + highestdB: gst.debug("found mix-in point of %f dB at %s" % ( peakdB, gst.TIME_ARGS(time))) self.mixin = time break # reverse and find out point self._peaksdB.reverse() found = None for (time, peakdB) in self._peaksdB: if found: self.mixout = time gst.debug("found mix-out point of %f dB right before %s" % ( found, gst.TIME_ARGS(time))) break if peakdB > self._thresholddB + highestdB: found = peakdB # now calculate RMS between these two points weightedsquaresums = 0.0 lasttime = self.mixin for (time, meansquaresum) in self._meansquaresums: if time <= self.mixin: continue delta = time - lasttime weightedsquaresums += meansquaresum * delta gst.log("added MSS %f over time %s at time %s, now %f" % ( meansquaresum, gst.TIME_ARGS(delta), gst.TIME_ARGS(time), weightedsquaresums)) lasttime = time if time > self.mixout: break # calculate try: ms = weightedsquaresums / (self.mixout - self.mixin) except ZeroDivisionError: # this is possible when, for example, the whole sound file is # empty gst.warning('ZeroDivisionError on %s, mixin %s, mixout %s' % ( self._filename, gst.TIME_ARGS(self.mixin), gst.TIME_ARGS(self.mixout))) self.emit('done', WRONG_TYPE) return self.rms = math.sqrt(ms) self.rmsdB = 10 * math.log10(ms) self.emit('done', EOS)