Exemple #1
0
 def lineReceived(self, raw_message):
     try:
         log.debug('ctrl:mpv: received %s' % raw_message)
         msg = json.loads(raw_message.decode('utf-8'))
     except ValueError:
         self.transport.loseConnection()
     else:
         if 'request_id' in msg \
         and int(msg['request_id']) in self.__commands_cb:
             cb = self.__commands_cb[int(msg['request_id'])]
             cb.callback(msg)
         elif 'error' in msg:
             if msg['error'] != 'success':
                 self.factory.handler.error(msg['error'])
         elif 'event' in msg:
             try:
                 f = getattr(self.factory.handler,
                             'EVENT_%s' % msg['event'].replace('-', '_'))
             except AttributeError:
                 log.debug('ctrl:mpv: unknown event received: %s' %
                           msg['event'])
             else:
                 for unwanted_arg in ('event', 'id'):
                     if unwanted_arg in msg:
                         del msg[unwanted_arg]
                 f(**msg)
         else:
             log.err('ctrl:mpv: unhandled message received: %s' % msg)
Exemple #2
0
def str_to_bytes(data, encoding="utf-8", errors="strict"):
    try:
        return data.encode(encoding, errors=errors)
    except UnicodeDecodeError as ex:
        data = data.encode(encoding, errors="replace")
        log.err("Unable to encode string %s" % data)
        raise ex
Exemple #3
0
    def update(self, force=False, sync=False):
        if self.updating_state["running"]:
            log.err(_("A library update is already running"))
            return

        self.updating_state["id"] += 1
        if sync:  # synchrone update
            self.walk_directory('', force=force)
            self.state["last_update"] = time.time()
        else:  # asynchrone update
            self.updating_state["running"] = True
            defered = threads.deferToThread(self.update_in_thread, '', force)
            defered.pause()

            # Add callback functions
            defered.addCallback(lambda *x: self.end_update())

            # Add errback functions
            def error_handler(failure, db_class):
                # Log the exception to debug pb later
                failure.printTraceback()
                db_class.end_update(False)
                return False

            defered.addErrback(error_handler, self)

            defered.unpause()
        return dict([(self.TYPE + "_updating_db", self.updating_state["id"])])
Exemple #4
0
    def _find_timer_TS_(self, buffer):
        c = 0

        while c + TS_PACKET_LENGTH < len(buffer):
            if buffer[c] == buffer[c + TS_PACKET_LENGTH] == TS_SYNC:
                break
            c += 1
        else:
            return None

        while c + TS_PACKET_LENGTH < len(buffer):
            start = buffer[c + 1] & 0x40
            if not start:
                c += TS_PACKET_LENGTH
                continue

            tsid = ((buffer[c + 1] & 0x3F) << 8) + buffer[c + 2]
            adapt = (buffer[c + 3] & 0x30) >> 4

            offset = 4
            if adapt & 0x02:
                # meta info present, skip it for now
                offset += buffer[c + offset] + 1

            if adapt & 0x01:
                timestamp = self.ReadPESHeader(c + offset, buffer[c + offset:],
                                               tsid)[1]
                if timestamp is None:
                    # this should not happen
                    log.err('bad TS')
                    return None
                return c + offset + timestamp
            c += TS_PACKET_LENGTH
        return None
Exemple #5
0
    def __init__(self, file):
        core.AVContainer.__init__(self)
        # read the header
        h = file.read(12)
        if h[:4] not in (b"RIFF", b'SDSS', b'RMP3', ):
            raise ParseError('unsupported RIFF header: %s' % h[:4])

        self.has_idx = False
        self.header = {}
        self.junkStart = None
        self.infoStart = None
        self.type = h[8:12]
        if self.type == b'AVI ':
            self.mime = 'video/avi'
        elif self.type == b'WAVE':
            self.mime = 'audio/wav'
        try:
            while self._parseRIFFChunk(file):
                pass
        except IOError:
            log.err('error in file, stop parsing')

        self._find_subtitles(file.name)

        if not self.has_idx and self.media == core.MEDIA_AV:
            log.debug('WARNING: avi has no index')
            self._set('corrupt', True)
Exemple #6
0
 def __try_connect(self):
     if not self.factory.conn:
         if self.__connect_tries < 5:
             reactor.connectUNIX(self.socket_path(), self.factory)
             reactor.callLater(1, self.__try_connect)
         else:
             log.err('ctrl:mpv: Could not connect to player process, '
                     'giving up.')
Exemple #7
0
 def get_position(self):
     if self.bin is not None and Gst.State.NULL != self.__get_gst_state()\
             and self.bin.get_property('current-uri'):
         ok, p = self.bin.query_position(Gst.Format.TIME)
         if not ok:
             log.err(_("Gstreamer: unable to get stream position"))
             return 0
         p //= Gst.SECOND
         return p
     return 0
Exemple #8
0
 def end_update(self, result=True):
     self.updating_state["running"] = False
     if result:
         log.msg(_("The %s library has been updated") % self.TYPE)
         self.dispatch_signame(self.UPDATE_SIGNAL_NAME)
         self.state["last_update"] = time.time()
     else:
         msg = _("Unable to update the %s library. See log.") % self.TYPE
         log.err(msg)
         self.updating_state["error"] = msg
     return True
Exemple #9
0
    def add_webradio(self, source, name, urls, cat=None):
        provided_urls = []
        for url in urls:
            if url.lower().startswith("http://") or \
               url.lower().startswith("https://"):
                try:
                    if url.lower().endswith(".pls"):
                        provided_urls.extend(get_uris_from_pls(url))
                    elif url.lower().endswith(".m3u"):
                        provided_urls.extend(get_uris_from_m3u(url))
                    else:
                        provided_urls.append(url)
                except IOError:
                    log.err(_("Could not parse %s") % url)
                    pass

        needed_urls = []
        for url in provided_urls:
            try:
                protocol = url.split(':')[0]
                if protocol not in (
                        'http',
                        'https',
                        'rtsp',
                ):
                    raise ValueError
            except ValueError:
                log.err(
                    _("Discarding %s : webradio protocol not supported.") %
                    url)
            else:
                if url not in needed_urls:
                    needed_urls.append(url)

        if len(needed_urls) < 1:
            raise DeejaydError(
                _("Given urls %s is not "
                  "supported") % ",".join(urls))
        cats = cat is not None and [cat] or []

        webradio = Session.query(Webradio)\
                          .filter(Webradio.source == source)\
                          .filter(Webradio.name == name)\
                          .one_or_none()
        if webradio is not None:
            raise DeejaydError(_("Webradio %s already exists") % name)
        webradio = Webradio(source=source, name=name)
        Session.add(webradio)

        for c in cats:
            webradio.categories.append(Session.query(WebradioCategory).get(c))
        for url in needed_urls:
            webradio.entries.append(WebradioEntry(url=url))
Exemple #10
0
 def __message(self, bus, message):
     if message.type == Gst.MessageType.EOS:
         self._end()
     elif message.type == Gst.MessageType.TAG:
         self.__update_metadata(message.parse_tag())
     elif message.type == Gst.MessageType.ERROR:
         err, debug = message.parse_error()
         log.err("Gstreamer Error: %s" % str(err))
         log.debug("Gstreamer Error debug: %s" % str(debug))
     elif message.type == Gst.MessageType.STREAM_START:
         if self.__in_gapless_transition:
             self._end()
     return True
Exemple #11
0
    def __init__(self, start_inotify=True, library_update=True):
        super(DeejayDaemonCore, self).__init__()
        config = DeejaydConfig()

        self.player = player.init(config)
        self.put_sub_handler('player', self.player)

        self.audiolib, self.videolib, self.watcher = library.init(self.player,
                                                                  config)
        self.put_sub_handler('audiolib', self.audiolib)
        if self.videolib is not None:
            self.put_sub_handler('videolib', self.videolib)

        self.recpls = DeejaydRecordedPlaylist(self.audiolib)
        self.put_sub_handler('recpls', self.recpls)

        # add audio queue/playlist and video playlist
        self.sources = sources.init(self.player, self.audiolib,
                                    self.videolib, config)
        for source in list(self.sources.sources.values()):
            self.put_sub_handler(source.name, source)
            setattr(self, source.name, source)

        # add webradio if player can play http stream
        if self.player.is_supported_uri("http"):
            self.webradio = DeejaydWebradio(self.player)
            self.put_sub_handler('webradio', self.webradio)
        else:
            log.err(_("Player is not able to play http streams"))
            self.webradio = None

        if library_update:
            self.audiolib.update()
            if self.videolib is not None:
                self.videolib.update()

        # enable JSON-RPC introspection
        self.put_sub_handler('introspection', JSONRPCIntrospection(self))

        # start inotify thread when we are sure that all init stuff are ok
        if self.watcher and start_inotify:
            log.debug(_("Start inotify watcher"))
            self.watcher.start()
        # record changes and close session after the initialization
        Session.commit()
        Session.remove()
Exemple #12
0
    def build_entity(self, inbuf):
        self.compute_id(inbuf)

        if self.id_len == 0:
            log.err('EBML entity not found, bad file format')
            raise ParseError()

        self.entity_len, self.len_size = self.compute_len(inbuf[self.id_len:])
        self.entity_data = inbuf[self.get_header_len() : self.get_total_len()]
        self.ebml_length = self.entity_len
        self.entity_len = min(len(self.entity_data), self.entity_len)

        # if the data size is 8 or less, it could be a numeric value
        self.value = 0
        if self.entity_len <= 8:
            for pos, shift in zip(list(range(self.entity_len)), list(range((self.entity_len - 1) * 8, -1, -8))):
                self.value |= self.entity_data[pos] << shift
Exemple #13
0
    def lineReceived(self, line):
        # use str instead of bytes to decode json commands
        # and return answer
        line = line.strip(b"\r").decode("utf-8")
        delimiter = self.delimiter.decode("utf-8")

        try:
            parsed = loads_request(line)
            args, function_path = parsed['params'], parsed["method"]
            if function_path.startswith("signal"):
                # it's a command linked with this connection
                method = function_path.split(self.separator, 1)[1]
                function = self.get_function(method)
            elif function_path == "close":
                function = self.close
            else:
                function = self.deejayd_core.get_function(function_path)
        except Fault as f:
            try:
                r_id = parsed["id"]
            except:
                r_id = None
            ans = JSONRPCResponse(f, r_id)
        else:
            # explicitly init session for this request
            Session()
            try:
                result = function(*args)
                Session.commit()
            except Exception as ex:
                Session.rollback()
                if not isinstance(ex, Fault):
                    log.err(traceback.format_exc())
                    result = Fault(self.FAILURE, _("error, see deejayd log"))
                else:
                    result = ex
            finally:
                Session.remove()
            ans = JSONRPCResponse(result, parsed["id"])

        self.send_buffer(ans.to_json()+delimiter)
        if self.__need_to_close:
            self.transport.loseConnection()
            self.__need_to_close = False
Exemple #14
0
def init(player, config):
    audio_library, video_library, lib_watcher = None, None, None

    audio_dir = config.get("mediadb", "music_directory")
    try:
        audio_library = AudioLibrary(audio_dir)
    except DeejaydError as msg:
        log.err(_("Unable to init audio library : %s") % msg, fatal=True)

    if config.getboolean("video", "enabled"):
        video_dir = config.get('mediadb', 'video_directory')
        try:
            video_library = VideoLibrary(video_dir)
        except DeejaydError as msg:
            log.err(_("Unable to init video library : %s") % msg, fatal=True)

    if inotify is not None:
        lib_watcher = inotify.DeejaydInotify(audio_library, video_library)

    return audio_library, video_library, lib_watcher
Exemple #15
0
def init(config):
    media_backend = config.get("general", "media_backend")

    if media_backend == "auto":
        backend_it = iter([DEFAULT_BACKEND] + AVAILABLE_BACKENDS)
        media_backend = None
        try:
            while not media_backend:
                backend = next(backend_it)
                try:
                    backend_module = get_backend_module(backend)
                except ImportError:
                    # Do nothing, simply ignore
                    pass
                else:
                    media_backend = backend
                    config.set('general', 'mediabackend', backend)
                    log.msg(_("Autodetected %s backend." % backend))
        except StopIteration:
            log.err(_("Could not find suitable media backend."), fatal=True)
    elif media_backend in AVAILABLE_BACKENDS:
        backend_module = get_backend_module(media_backend)
    else:
        log.err(_("Invalid media backend %s" % media_backend), fatal=True)

    try:
        player_class = getattr(backend_module,
                               '%sPlayer' % media_backend.capitalize())
        player = player_class(config)
    except PlayerError as err:
        log.err(str(err), fatal=True)

    return player
Exemple #16
0
    def _parseAVIH(self, t):
        retval = {}
        v = struct.unpack('<IIIIIIIIIIIIII', t[0:56])
        (retval['dwMicroSecPerFrame'],
          retval['dwMaxBytesPerSec'],
          retval['dwPaddingGranularity'],
          retval['dwFlags'],
          retval['dwTotalFrames'],
          retval['dwInitialFrames'],
          retval['dwStreams'],
          retval['dwSuggestedBufferSize'],
          retval['dwWidth'],
          retval['dwHeight'],
          retval['dwScale'],
          retval['dwRate'],
          retval['dwStart'],
          retval['dwLength']) = v
        if retval['dwMicroSecPerFrame'] == 0:
            log.err("ERROR: Corrupt AVI")
            raise ParseError()

        return retval
Exemple #17
0
 def error(self, msg):
     log.err('ctrl:mpv: error received: %s' % msg)
Exemple #18
0
 def processEnded(self, status):
     if status.value.exitCode not in self.manager.EXIT_SUCCESS:
         log.err('ctrl: child process ended with status: %s' % status)
     self.manager._process_gone()
Exemple #19
0
 def __on_reload_error(self, failure):
     log.err(_("Unable to update icecast webradio, see exception below"))
     log.err(failure)
Exemple #20
0
 def lineLengthExceeded(self, line):
     log.err(_("Request too long, close the connection"))
     self.transport.loseConnection()
Exemple #21
0
    def _readatom(self, file):
        s = file.read(8)
        if len(s) < 8:
            return 0

        atomsize, atomtype = struct.unpack('>I4s', s)
        if not atomtype.decode('latin1').isalnum():
            # stop at nonsense data
            return 0

        log.debug('%r [%X]' % (atomtype, atomsize))

        if atomtype == b'udta':
            # Userdata (Metadata)
            pos = 0
            tabl = {}
            i18ntabl = {}
            atomdata = file.read(atomsize - 8)
            while pos < atomsize - 12:
                (datasize, datatype) = struct.unpack('>I4s',
                                                     atomdata[pos:pos + 8])
                if datatype[0] == 169:
                    # i18n Metadata...
                    mypos = 8 + pos
                    while mypos + 4 < datasize + pos:
                        # first 4 Bytes are i18n header
                        (tlen, lang) = struct.unpack('>HH',
                                                     atomdata[mypos:mypos + 4])
                        i18ntabl[lang] = i18ntabl.get(lang, {})
                        l = atomdata[mypos + 4:mypos + tlen + 4]
                        i18ntabl[lang][datatype[1:]] = l
                        mypos += tlen + 4
                elif datatype == b'WLOC':
                    # Drop Window Location
                    pass
                else:
                    if atomdata[pos + 8:pos + datasize][0] > 1:
                        tabl[datatype] = atomdata[pos + 8:pos + datasize]
                pos += datasize
            if len(i18ntabl) > 0:
                for k in i18ntabl:
                    if k in QTLANGUAGES and QTLANGUAGES[k] == 'en':
                        self._appendtable('QTUDTA', i18ntabl[k])
                        self._appendtable('QTUDTA', tabl)
            else:
                log.debug('NO i18')
                self._appendtable('QTUDTA', tabl)

        elif atomtype == b'trak':
            atomdata = file.read(atomsize - 8)
            pos = 0
            trackinfo = {}
            tracktype = None
            while pos < atomsize - 8:
                (datasize, datatype) = struct.unpack('>I4s',
                                                     atomdata[pos:pos + 8])

                if datatype == b'tkhd':
                    tkhd = struct.unpack('>6I8x4H36xII',
                                         atomdata[pos + 8:pos + datasize])
                    trackinfo['width'] = tkhd[10] >> 16
                    trackinfo['height'] = tkhd[11] >> 16
                    trackinfo['id'] = tkhd[3]

                    try:
                        # XXX Timestamp of Seconds is since January 1st 1904!
                        # XXX 2082844800 is the difference between Unix and
                        # XXX Apple time. FIXME to work on Apple, too
                        self.timestamp = int(tkhd[1]) - 2082844800
                    except Exception as e:
                        log.err('There was trouble extracting timestamp')

                elif datatype == b'mdia':
                    pos += 8
                    datasize -= 8
                    log.debug('--> mdia information')

                    while datasize:
                        mdia = struct.unpack('>I4s', atomdata[pos:pos + 8])
                        if mdia[1] == b'mdhd':
                            # Parse based on version of mdhd header.  See
                            # http://wiki.multimedia.cx/index.php?title=QuickTime_container#mdhd
                            ver = atomdata[pos + 8]
                            if ver == 0:
                                mdhd = struct.unpack(
                                    '>IIIIIhh', atomdata[pos + 8:pos + 8 + 24])
                            elif ver == 1:
                                mdhd = struct.unpack(
                                    '>IQQIQhh', atomdata[pos + 8:pos + 8 + 36])
                            else:
                                mdhd = None

                            if mdhd:
                                # duration / time scale
                                trackinfo['length'] = mdhd[4] / mdhd[3]
                                if mdhd[5] in QTLANGUAGES:
                                    trackinfo['language'] = QTLANGUAGES[
                                        mdhd[5]]
                                # mdhd[6] == quality
                                self.length = max(self.length,
                                                  mdhd[4] / mdhd[3])
                        elif mdia[1] == b'minf':
                            # minf has only atoms inside
                            pos -= (mdia[0] - 8)
                            datasize += (mdia[0] - 8)
                        elif mdia[1] == b'stbl':
                            # stbl has only atoms inside
                            pos -= (mdia[0] - 8)
                            datasize += (mdia[0] - 8)
                        elif mdia[1] == b'hdlr':
                            hdlr = struct.unpack(
                                '>I4s4s', atomdata[pos + 8:pos + 8 + 12])
                            if hdlr[1] == b'mhlr':
                                if hdlr[2] == b'vide':
                                    tracktype = 'video'
                                if hdlr[2] == b'soun':
                                    tracktype = 'audio'
                        elif mdia[1] == b'stsd':
                            stsd = struct.unpack('>2I',
                                                 atomdata[pos + 8:pos + 8 + 8])
                            if stsd[1] > 0:
                                codec = atomdata[pos + 16:pos + 16 + 8]
                                codec = struct.unpack('>I4s', codec)
                                trackinfo['codec'] = codec[1]
                                if codec[1] == b'jpeg':
                                    tracktype = 'image'
                        elif mdia[1] == b'dinf':
                            dref = struct.unpack('>I4s',
                                                 atomdata[pos + 8:pos + 8 + 8])
                            log.debug('  --> %r, %r (useless)' % mdia)
                            if dref[1] == b'dref':
                                num = struct.unpack(
                                    '>I', atomdata[pos + 20:pos + 20 + 4])[0]
                                rpos = pos + 20 + 4
                                for ref in range(num):
                                    # FIXME: do somthing if this references
                                    ref = struct.unpack(
                                        '>I3s', atomdata[rpos:rpos + 7])
                                    data = atomdata[rpos + 7:rpos + ref[0]]
                                    rpos += ref[0]
                        else:
                            if mdia[1].startswith(b'st'):
                                log.debug('  --> %r, %r (sample)' % mdia)
                            elif mdia[1] == b'vmhd' and not tracktype:
                                # indicates that this track is video
                                tracktype = 'video'
                            elif mdia[1] in [b'vmhd', b'smhd'
                                             ] and not tracktype:
                                # indicates that this track is audio
                                tracktype = 'audio'
                            else:
                                log.debug('  --> %r, %r (unknown)' % mdia)

                        pos += mdia[0]
                        datasize -= mdia[0]

                elif datatype == b'udta':
                    log.debug(str(struct.unpack('>I4s', atomdata[:8])))
                else:
                    if datatype == b'edts':
                        log.debug('--> %r [%d] (edit list)' % \
                                  (datatype, datasize))
                    else:
                        log.debug('--> %r [%d] (unknown)' % \
                                  (datatype, datasize))
                pos += datasize

            info = None
            if tracktype == 'video':
                info = core.VideoStream()
                self.video.append(info)
            if tracktype == 'audio':
                info = core.AudioStream()
                self.audio.append(info)
            if info:
                for key, value in list(trackinfo.items()):
                    setattr(info, key, value)

        elif atomtype == b'mvhd':
            # movie header
            mvhd = struct.unpack('>6I2h', file.read(28))
            self.length = max(self.length, mvhd[4] / mvhd[3])
            self.volume = mvhd[6]
            file.seek(atomsize - 8 - 28, 1)

        elif atomtype == b'cmov':
            # compressed movie
            datasize, atomtype = struct.unpack('>I4s', file.read(8))
            if not atomtype == b'dcom':
                return atomsize

            method = struct.unpack('>4s', file.read(datasize - 8))[0]

            datasize, atomtype = struct.unpack('>I4s', file.read(8))
            if not atomtype == b'cmvd':
                return atomsize

            if method == b'zlib':
                data = file.read(datasize - 8)
                try:
                    decompressed = zlib.decompress(data)
                except Exception as e:
                    try:
                        decompressed = zlib.decompress(data[4:])
                    except Exception as e:
                        log.err('There was a proble decompressiong atom')
                        return atomsize

                decompressedIO = io.StringIO(decompressed)
                while self._readatom(decompressedIO):
                    pass

            else:
                log.info('unknown compression %r' % method)
                # unknown compression method
                file.seek(datasize - 8, 1)

        elif atomtype == b'moov':
            # decompressed movie info
            while self._readatom(file):
                pass

        elif atomtype == b'mdat':
            pos = file.tell() + atomsize - 8
            # maybe there is data inside the mdat
            log.info('parsing mdat')
            while self._readatom(file):
                pass
            log.info('end of mdat')
            file.seek(pos, 0)

        elif atomtype == b'rmra':
            # reference list
            while self._readatom(file):
                pass

        elif atomtype == b'rmda':
            # reference
            atomdata = file.read(atomsize - 8)
            pos = 0
            url = ''
            quality = 0
            datarate = 0
            while pos < atomsize - 8:
                (datasize, datatype) = struct.unpack('>I4s',
                                                     atomdata[pos:pos + 8])
                if datatype == b'rdrf':
                    rflags, rtype, rlen = struct.unpack(
                        '>I4sI', atomdata[pos + 8:pos + 20])
                    if rtype == b'url ':
                        url = atomdata[pos + 20:pos + 20 + rlen]
                        if url.find('\0') > 0:
                            url = url[:url.find('\0')]
                elif datatype == b'rmqu':
                    quality = struct.unpack('>I',
                                            atomdata[pos + 8:pos + 12])[0]

                elif datatype == b'rmdr':
                    datarate = struct.unpack('>I',
                                             atomdata[pos + 12:pos + 16])[0]

                pos += datasize
            if url:
                self._references.append((url, quality, datarate))

        else:
            if not atomtype in [b'wide', b'free']:
                log.info('unhandled base atom %r' % atomtype)

            # Skip unknown atoms
            try:
                file.seek(atomsize - 8, 1)
            except IOError:
                return 0

        return atomsize