Ejemplo n.º 1
0
    def queue_next(self,step=1):
        """
        Advances 1 position in queue.
        case player state:
          - playing: the new track will start playing
          - paused : the current track will be preserved. new track will be played
          only if user inputs 'next' or ['stop','play'].
          - stopped: the new track will not be played until client sends 'play'

        Return values:
          - If successful [200,positions_moved]
          - else: [error_code]
        """
        ans = [400]
        try:
            gst.debug('Will next_prev(%d)' % step)
            ok,moved = self.next_prev(step)
            gst.debug('next_prev(%d) returned (%f,%d)' % (step,ok,moved))
            if ok:
                ans = [200]
                ans.append(moved)
        except Exception as e:
            print e
            gst.error('Problem near queue_next()')
        return ans
Ejemplo n.º 2
0
    def status(self):
        """
        Get player playing/!playing

        If metadata is available, then the answer will include it.

        Return value:
          - If successful: [200,True/False,metadata]
          - else: [err_code]
        """
        ans = [200]
        try:
            gst.debug(self.queue.__str__())
            playing = self.is_playing()
            current = self.player.get_current()
            tags    = self.queue_item_by_uri(current)
            if not tags:
                # Failed to find tags or search is still
                # in progress
                tags = {}
            ans.append([playing,current,tags])
        except Exception as e:
            print e
            gst.error('Problem near status()')
            ans = [400]
        return ans
Ejemplo n.º 3
0
 def bus_message_eos (self, bus, message):
     """
     Callback for gst.MESSAGE_EOS, will
     give up on tag search
     """
     gst.error('Got eos, will abort')
     self.quit()
Ejemplo n.º 4
0
 def start_recording(self):
     structure = gst.Structure("shifter-start-recording")
     event = gst.event_new_custom(gst.EVENT_CUSTOM_UPSTREAM, structure)
     res = self.pipeline.send_event(event)
     if res:
         print "start recording"
     else:
         gst.error("start recording failed")
Ejemplo n.º 5
0
 def get_current(self):
     ans = []
     try:
         ans = self.player.get_property('uri')
     except Exception as e:
         err_msg = 'Failed to get current. Exception:%s' % e.__str__()
         gst.error(err_msg)
     return ans
Ejemplo n.º 6
0
 def start_recording(self):
     structure = gst.Structure ("shifter-start-recording")
     event = gst.event_new_custom (gst.EVENT_CUSTOM_UPSTREAM, structure)
     res = self.pipeline.send_event(event)
     if res:
         print "start recording"
     else:
         gst.error("start recording failed")
Ejemplo n.º 7
0
 def bus_message_err (self, bus, message):
     """
     Callback for gst.MESSAGE_ERROR, will
     give up on tag search
     """
     err, debug = message.parse_error()
     err_msg = 'Got error message, will abort:%s ' % err, debug
     gst.error(err_msg)
     self.quit()
Ejemplo n.º 8
0
    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
Ejemplo n.º 9
0
    def seek_end(self):
        event = gst.event_new_seek(
            1.0, gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE,
            gst.SEEK_TYPE_END, -1, gst.SEEK_TYPE_NONE, 0)

        res = self.pipeline.send_event(event)
        if res:
            gst.info("setting new stream time to 0")
        else:
            gst.error("seek to end failed")
Ejemplo n.º 10
0
	def playEpisode (self, view, episode):
		gst.info('Playing episode ' + episode.title)
		mrl = episode.getUri(self.getConnectionSpeed())
		if mrl:
		  gst.log('Playing uri ' + mrl)
		  self.totem.action_set_mrl_and_play(mrl, None)
		  #self.totem.action_remote(totem.REMOTE_COMMAND_ENQUEUE, mrl)
		  #self.totem.action_remote(totem.REMOTE_COMMAND_PLAY, mrl)
		else:
		  gst.error('No uri for episode ' + episode.title)
Ejemplo n.º 11
0
    def next_prev(self, step):
        """
        Move queue step positions (next,back)
        Returns a tuple (ok,queue_moved), where
        the value queue_moved indicates number of postions
        shifted by queue_move(), and is valid only if ok==True
        """
        ans         = False
        queue_moved = 0
        if(step == 0):
            # come on...
            return ans,queue_moved
        elif not self.queue:
            # queue is empty
            gst.debug('queue is empty')
            ans = True
            return ans,queue_moved
        try:
            queue_pos_old   = self.queue_pos
            queue_pos_new   = self.queue_pos + step
            queue_finished  = False
            # Verify index is within limits, stop if out of boundries
            # This is the typical behaviour of mp3 playing software
            # such as Rhythmbox.
            if queue_pos_new < 0 or queue_pos_new >= len(self.queue):
                gst.debug('queue playback completed, will stop and return to first element')
                # queue completed, stop player and return
                queue_pos_new  = 0
                queue_finished = True
            queue_moved = abs(queue_pos_new - queue_pos_old)

            uri_new = self.queue[queue_pos_new]['uri']
            gst.debug('Will set new location to %s' % uri_new)
            self.player.set_location(uri_new)
            # update queue position
            self.queue_pos = queue_pos_new
            gst.debug('New queue_pos:%d/%d' % (self.queue_pos, len(self.queue)))
            try:
                if(self.is_playing()):
                    gst.debug('Will stop+play to advance in queue')
                    self.stop()
                    if queue_finished:
                        gst.debug('Omiting play(), queue finished')
                    else:
                        self.play()
                # Mark success
                ans = True
            except Exception as e:
                print e
                gst.error('Failed to advance in queue')
        except Exception as e:
            print e
            gst.error('Problem near next()')
        return ans,queue_moved
Ejemplo n.º 12
0
 def help_msg(self):
     """
     Returns help message string.
     """
     menu  = "\n-- Help menu --\n\nValid commands:\n\t"
     try:
         funcs = '\n\t'.join(self.handlers.keys())
     except:
         gst.error('Failed to build handler list')
         funcs = []
     return "%s%s" % (menu,funcs)
Ejemplo n.º 13
0
    def seek_end(self):
        event = gst.event_new_seek(1.0, gst.FORMAT_TIME,
            gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE,
            gst.SEEK_TYPE_END, -1,
            gst.SEEK_TYPE_NONE, 0)

        res = self.pipeline.send_event(event)
        if res:
            gst.info("setting new stream time to 0")
        else:
            gst.error("seek to end failed")
Ejemplo n.º 14
0
    def seek(self, location):
        gst.debug("seeking to %r" % location)
        event = gst.event_new_seek(1.0, gst.FORMAT_TIME,
            gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE,
            gst.SEEK_TYPE_SET, location,
            gst.SEEK_TYPE_NONE, 0)

        res = self.player.send_event(event)
        if res:
            gst.info("setting new stream time to 0")
            self.player.set_new_stream_time(0L)
        else:
            gst.error("seek to %r failed" % location)
Ejemplo n.º 15
0
 def is_playing(self):
     """
     Wrapper for player.is_playing()
     """
     playing = False
     try:
         playing = self.player.is_playing()
         if self.src == 'stdin':
             print "Player state: Playing" if playing else "Player state: NOT Playing"
         gst.debug('status:%r' % playing)
     except Exception as e:
         print e
         gst.error('Problem near is_playing()')
     return playing
Ejemplo n.º 16
0
 def seek(self, location):
     """
     @param location: time to seek to, in nanoseconds
     """
     gst.debug("seeking to %r" % location)
     event = gst.event_new_seek(
         1.0, gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE,
         gst.SEEK_TYPE_SET, location, gst.SEEK_TYPE_NONE, 0)
     res = self.player.send_event(event)
     if res:
         gst.info("setting new stream time to 0")
         self.player.set_new_stream_time(0L)
     else:
         gst.error("seek to %r failed" % location)
Ejemplo n.º 17
0
 def seek(self, location):
     """
     @param location: time to seek to, in nanoseconds
     """
     # gst.debug("seeking to %r" % location)
     event = gst.event_new_seek(1.0, gst.FORMAT_TIME,
         gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE,
         gst.SEEK_TYPE_SET, location,
         gst.SEEK_TYPE_NONE, 0)
     res = self._pipeline.send_event(event)
     if res:
         # gst.info("setting new stream time to 0")
         self._pipeline.set_new_stream_time(0L)
     else:
         gst.error("seek to %r failed" % location)
Ejemplo n.º 18
0
 def queue_prev(self,step=-1):
     """
     Just like 'queue_next()' but backwards'
     """
     ans = [400]
     if step >= 0:
         return ans
     try:
         ok,moved = self.next_prev(step)
         if ok:
             ans = [200]
             ans.append(moved)
     except Exception as e:
         print e
         gst.error('Problem near queue_prev()')
     return ans
Ejemplo n.º 19
0
    def fast_forward(self):
        """
            Here we will fast forward the stream for as many times
            as this is called
        """
        if self.rate < 8.0:
            self.rate = self.rate*2.0
            event = gst.event_new_seek(self.rate, gst.FORMAT_TIME,
                gst.SEEK_FLAG_FLUSH,
                gst.SEEK_TYPE_SET, self.query_position()[0],
                gst.SEEK_TYPE_NONE, 0)

            res = self.player.send_event(event)
            if res:
                gst.info("fast forwarding at rate: %f" % self.rate)
                self.player.set_new_stream_time(0L)
            else:
                gst.error("change rate to %f failed" % self.rate)
        return
Ejemplo n.º 20
0
    def slow_motion(self):
        """
            Here we will slow motion the stream for as many times
            as this is called
        """
        self.rate = self.rate/2.0
        event = gst.event_new_seek(self.rate, gst.FORMAT_TIME,
            gst.SEEK_FLAG_FLUSH,
            gst.SEEK_TYPE_SET, self.query_position()[0],
            gst.SEEK_TYPE_NONE, 0)

        res = self.player.send_event(event)
        if res:
            gst.info("slowing playback to rate: %f" % self.rate)
            self.player.set_new_stream_time(0L)
        else:
            gst.error("change rate to %f failed" % self.rate)

        return
Ejemplo n.º 21
0
    def play(self):
        """
            Change the stream state to playing or simply
            change its playing rate to normal rate
        """
        if self.rate != 1.0:
            self.rate = 1.0
            event = gst.event_new_seek(self.rate, gst.FORMAT_TIME,
                gst.SEEK_FLAG_FLUSH,
                gst.SEEK_TYPE_SET, self.query_position()[0],
                gst.SEEK_TYPE_NONE, 0)

            res = self.player.send_event(event)
            if res:
                gst.info("slowing playback to rate: %f" % self.rate)
                self.player.set_new_stream_time(0L)
            else:
                gst.error("change rate to %f failed" % self.rate)           
        else:
            gst.info("playing player")
            self.player.set_state(gst.STATE_PLAYING)
            self.playing = True
        return
Ejemplo n.º 22
0
    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
Ejemplo n.º 23
0
    def _decode(self,callback,width=None,height=None,\
                   format=None,depth=None,bpp=None):

        if not width or not height or not format :
            raise NameError("Failed to init decoder without format,"\
                                +" or height or width")

        begin = self.video.begin
        end   = self.video.end

        #init gstreamer 
        caps="video/%s,width=%i,height=%i"\
            % (format,width,height)

        if depth  : 
            caps+=",depth=%i" % depth 
        if bpp  : 
            caps+=",bpp=%i" % bpp

        pip_desc ="uridecodebin uri=%s ! ffmpegcolorspace !  videoscale ! appsink name=sink " % self.video.uri
        pipeline = gst.parse_launch(pip_desc)

        self.appsink = pipeline.get_by_name("sink")
        self.appsink.set_property('emit-signals', True)
        self.appsink.set_property('sync', False)
        self.appsink.set_property('caps', gst.caps_from_string(caps))
        
        if pipeline.set_state(gst.STATE_PLAYING) == gst.STATE_CHANGE_FAILURE:
            raise NameError("Failed to load uri video (example file:///home/... )%s" % self.video.uri)

	buff = self.appsink.emit('pull-preroll')

	#seek if necessary 
        if begin > 0 or end is not None : 
            self.log.info("seek in video from %d to %d" % (begin,end))
            flags = gst.SEEK_FLAG_FLUSH        
            flags |= gst.SEEK_FLAG_ACCURATE 

            res = pipeline.seek(
                1.0,                            # normal-speed playback
                gst.FORMAT_TIME,                # time-based seek
                flags,       
                gst.SEEK_TYPE_SET, begin*gst.SECOND,
                gst.SEEK_TYPE_SET, end*gst.SECOND)
            res = pipeline.seek_simple(gst.FORMAT_TIME,flags, begin*gst.SECOND)

            if res:                
		pipeline.set_new_stream_time(0L)
            else:
                gst.error("seek to %r failed" % begin)
                raise NameError("seek failed")

        #start video decoding
	framenumber = 0
        while True :
            buff = self.appsink.emit('pull-buffer')
            if not buff : break 
            f = pimpy.video.Frame(**{
                  "video" : self.video , 
                  "framenumber" : framenumber,
		  "data" : buff.data, 
		  "format": format ,
	          "width" : width,
	          "height" : height })

            f.position = pipeline.query_position(gst.Format(gst.FORMAT_TIME), None)[0]

            #send frame decoded to the callback function
            callback(f)
            framenumber+=1 

        #Decode step finish
        self.video.framenumber = framenumber 
	pipeline.set_state(gst.STATE_NULL)
	pipeline = None 
Ejemplo n.º 24
0
 def do_state_change(self, transition):
     if not self._prerolled:
         gst.error("Call Jukebox.preroll() before!")
         return gst.STATE_CHANGE_FAILURE
     # chaining up
     return gst.Bin.do_state_change(self, message)
Ejemplo n.º 25
0
    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)
Ejemplo n.º 26
0
 def do_state_change(self, transition):
     if not self._prerolled:
         gst.error("Call Jukebox.preroll() before!")
         return gst.STATE_CHANGE_FAILURE
     # chaining up
     return gst.Bin.do_state_change(self, message)