示例#1
0
    def start(self):
        pid = self.read_pid()
        if pid:
            log.error(u"Server already running, pid %s." % pid)
            sys.exit(-1)
        else:
            self.write_pid(os.getpid())

        server = None
        try:
            time.sleep(0.001)
            server = Server((Config.hostname, self.port))
            log.info(u"Bloops and bleeps at http://%s:%s" %
                     server.server_address)
            server.serve_forever()
            # will never reach this line
        except socket.error, se:
            if se.errno == errno.EACCES:
                log.warn(u"Bad port: %s" % self.port)
                sys.exit(se.errno)
            elif se.errno == errno.ECONNREFUSED:
                log.warn(u"Connection refused: %s" % self.port)
                sys.exit(se.errno)
            else:
                log.exception(se)
示例#2
0
    def run(self):
        # well this is just fugly.  call it "experimental"
        while Config.running:
            try:
                scrobble_item = self.queue.get(0)
                try:
                    song = scrobble_item.song
                    type = scrobble_item.type
                    error = scrobble_item.error
                    etime = scrobble_item.etime

                    try:
                        (tracknumber, artist, album, track) = [escape(item) for item in song.tags]
                    except ValueError:
                        log.info("skipping scrobble for {} (bad tags)".format(song.path))
                        continue

                    if type == NOW_PLAYING:
                        log.debug(u"scrobbling now playing %s %s %s" %
                                (artist, track, album))
                        self.login()
                        scrobbler.now_playing(
                                artist,
                                track)
                        # now_playing auto flushes, apparently.  don't call
                        # flush here or it will throw an exception, which is not
                        # what we want.
                    elif type == PLAYED:
                        # See: http://exhuma.wicked.lu/projects/python/scrobbler/api/public/scrobbler-module.html#login
                        # if mimetype is wrong, length == 0
                        if song.length < 30: log.warn(u"song length %s" % song.length)

                        # wait 60 seconds before re-trying
                        # submission
                        if error:
                            if (time.time() - etime) < 60:
                                break
                        log.debug(u"scrobbling played %s %s %s %s" %
                                (artist, track, album, song.length))
                        self.login()
                        scrobbler.submit(
                            artist,
                            track,
                            int(time.mktime(datetime.datetime.now().timetuple())),
                            source=escape(u'P'),
                            length=song.length,
                            album=album)
                        scrobbler.flush()
                except Exception as e:
                    log.exception(u"scrobble error: %s" % e)
                    # put it back
                    scrobble_item.error = True
                    scrobble_item.etime = time.time()
                    self.queue.put(scrobble_item)
            except Queue.Empty:
                pass

            # AS API enforced limit -- do not change.
            time.sleep(10)
示例#3
0
 def __init__(self, url: str, role: str = "server", max_workers: int = 5):
     threading.Thread.__init__(self)
     self.__url = url
     self.__role = role.lower()
     self.__max_workers = max_workers
     self.__worker_queue = set()
     if role.lower() not in ["server", "client"]:
         log.warn("没有相应的角色选择[role=%s],将设置为默认项[role=%s],可选项包括:%s" %
                  (self.__role, "server", ["server", "client"]))
         self.__role = "server"  # default
     self.__socket = None
示例#4
0
 def stop(self):
     time.sleep(0.1)
     pid = self.read_pid()
     if pid:
         try:
             set_data(self.port, u'running', False)
             #os.kill( pid, signal.SIGTERM)
         except OSError:  # already dead
             pass
         except socket.error, se:
             if se.errno == errno.ECONNREFUSED:
                 log.warn(u"not running")
         self.write_pid(u"")
示例#5
0
 def stop(self):
     time.sleep(0.1)
     pid = self.read_pid()
     if pid:
         try:
             set_data(self.port, u'running', False)
             #os.kill( pid, signal.SIGTERM)
         except OSError:  # already dead
             pass
         except socket.error, se:
             if se.errno == errno.ECONNREFUSED:
                 log.warn(u"not running")
         self.write_pid(u"")
示例#6
0
    def start(self):
        pid = self.read_pid()
        if pid:
            log.error("Server already running, pid %s." % pid)
            sys.exit( -1 )
        else:
            self.write_pid( os.getpid() )

        try:
            time.sleep(0.001)
            Server((Config.hostname, self.port))
            # will never reach this line
        except socket.error, se:
            if se.errno == errno.EACCES:
                log.warn("Bad port: %s" % self.port)
                sys.exit( se.errno )
            else:
                log.exception(se)
示例#7
0
    def start(self):
        pid = self.read_pid()
        if pid:
            log.error(u"Server already running, pid %s." % pid)
            sys.exit( -1 )
        else:
            self.write_pid( os.getpid() )

        server = None
        try:
            time.sleep(0.001)
            server = Server((Config.hostname, self.port))
            log.info(u"Bloops and bleeps at http://%s:%s" % server.server_address)
            server.serve_forever()
            # will never reach this line
        except socket.error, se:
            if se.errno == errno.EACCES:
                log.warn(u"Bad port: %s" % self.port)
                sys.exit( se.errno )
            elif se.errno == errno.ECONNREFUSED:
                log.warn(u"Connection refused: %s" % self.port)
                sys.exit( se.errno )
            else:
                log.exception(se)
示例#8
0
    def stream(self, icy_client=False):
        song = None
        while self.playlist.data[u'running']:
            if Config.scrobble and song:
                    # just played one . . . scrobble it
                    self.scrobble_queue.put(ScrobbleItem(PLAYED, song))
                    #log.debug("enqueued played")
                    #log.debug(song)

            # new song
            song            = self.playlist.get_song()
            song_start_time = time.time()
            self.playlist.data[u"progress"] = 0

            if not song:
                log.warn(u"no playlist, won't stream")
                self.playlist.data[u'status'] = u'stopped'
                self.byte_count = 0
                self.empty_scrobble_queue()
                return

            if Config.scrobble:
                #log.debug("enqueued now playing")
                self.scrobble_queue.put(ScrobbleItem(NOW_PLAYING, song))

            log.info(u'> %s' % unicode(song))

            transcode = None
            try:
                # this loop gets some of its ideas about the shoutcast protocol from Amarok
                buffer              = 0
                buffer_size         = Config.buffer_size
                metadata_interval   = Config.metaint

                try:
                    transcode.stdout.close()
                except:
                    pass

                #cif song.mimetype[0:5] in ["audio", "video"]:
                transcode = subprocess.Popen([u"/usr/bin/ffmpeg",
                                              u"-i", song.path,
                                              u"-vn",
                                              u"-loglevel", u"warning",
                                              u"-qscale:a", u"0",
                                              u"-f", u"mp3",
                                              u"-"],
                                             stdout=subprocess.PIPE,
                                             shell=False)
                self.dirty_meta = True

                skip = False
                while self.playlist.data[u'running'] and transcode:
                    bytes_until_meta = (metadata_interval - self.byte_count)
                    if bytes_until_meta == 0:
                        if icy_client:
                            metadata = self.get_meta(song)
                            self.request.send(metadata.encode(u'ascii', u'ignore'))
                        self.byte_count = 0
                    else:
                        if bytes_until_meta < buffer_size:
                            chunk_bytes = bytes_until_meta
                        else:
                            chunk_bytes = buffer_size
                        buffer = transcode.stdout.read(chunk_bytes)

                        self.request.send(buffer)
                        buflen = len(buffer)
                        self.byte_count                     += buflen
                        self.playlist.data[u"sum_bytes"]     += buflen
                        elapsed = time.time() - song_start_time
                        self.playlist.data[u'elapsed'] = elapsed
                        # set percentage elapsed
                        try:
                            self.playlist.data[u"progress"] = float(elapsed * 100) / song.length
                        except ZeroDivisionError:
                            self.playlist.data[u"progress"] = 0

                        if len(buffer) == 0: break

                    if self.playlist.data[u'skip']:
                        log.info(u">>")
                        skip = True
                        song = None  # don't scrobble
                        self.playlist.data[u"elapsed"] = 0
                        self.playlist.data[u"progress"] = 0
                        break

                    if self.playlist.data[u'status'] == u'stopped':
                        log.info(u".")
                        skip = True
                        song = None  # don't scrobble
                        self.playlist.data[u"elapsed"] = 0
                        break

                if not skip:
                    # increment the counter if we're not ffwding
                    self.playlist.next()
                else:
                    self.playlist.data[u'skip'] = False
                self.dirty_meta = True
            except error, e:
                if isinstance(e.args, tuple):
                    print "errno is %d" % e[0]
                    if e[0] == errno.EPIPE:
                        # remote peer disconnected
                        print "Detected remote disconnect"

                    elif e.errno == errno.ECONNRESET:
                        self.empty_scrobble_queue()
                        log.info(u"Client disconnected")
                    else:
                        log.info(u"Unknown socket error")
                        self.empty_scrobble_queue()
                        log.exception(errno.errorcode[e.errno])
                else:
                    print "socket error ", e
                self.request.close()
                self.playlist.data[u'status'] = 'stopped'
                break # while
            except IOError, e:
                log.info("IO ERROR")
示例#9
0
    def stream(self, icy_client=False):
        song = None
        while self.playlist.data[u'running']:
            if Config.scrobble and song:
                # just played one . . . scrobble it
                self.scrobble_queue.put(ScrobbleItem(PLAYED, song))
                #log.debug("enqueued played")
                #log.debug(song)

            # new song
            song = self.playlist.get_song()
            song_start_time = time.time()
            self.playlist.data[u"progress"] = 0

            if not song:
                log.warn(u"no playlist, won't stream")
                self.playlist.data[u'status'] = u'stopped'
                self.byte_count = 0
                self.empty_scrobble_queue()
                return

            if Config.scrobble:
                #log.debug("enqueued now playing")
                self.scrobble_queue.put(ScrobbleItem(NOW_PLAYING, song))

            log.info(u'> %s' % unicode(song))

            transcode = None
            try:
                # this loop gets some of its ideas about the shoutcast protocol from Amarok
                buffer = 0
                buffer_size = Config.buffer_size
                metadata_interval = Config.metaint

                try:
                    transcode.stdout.close()
                except:
                    pass

                #cif song.mimetype[0:5] in ["audio", "video"]:
                transcode = subprocess.Popen([
                    u"/usr/bin/ffmpeg", u"-i", song.path, u"-vn", u"-loglevel",
                    u"warning", u"-qscale:a", u"0", u"-f", u"mp3", u"-"
                ],
                                             stdout=subprocess.PIPE,
                                             shell=False)
                self.dirty_meta = True

                skip = False
                while self.playlist.data[u'running'] and transcode:
                    bytes_until_meta = (metadata_interval - self.byte_count)
                    if bytes_until_meta == 0:
                        if icy_client:
                            metadata = self.get_meta(song)
                            self.request.send(
                                metadata.encode(u'ascii', u'ignore'))
                        self.byte_count = 0
                    else:
                        if bytes_until_meta < buffer_size:
                            chunk_bytes = bytes_until_meta
                        else:
                            chunk_bytes = buffer_size
                        buffer = transcode.stdout.read(chunk_bytes)

                        self.request.send(buffer)
                        buflen = len(buffer)
                        self.byte_count += buflen
                        self.playlist.data[u"sum_bytes"] += buflen
                        elapsed = time.time() - song_start_time
                        self.playlist.data[u'elapsed'] = elapsed
                        # set percentage elapsed
                        try:
                            self.playlist.data[u"progress"] = float(
                                elapsed * 100) / song.length
                        except ZeroDivisionError:
                            self.playlist.data[u"progress"] = 0

                        if len(buffer) == 0: break

                    if self.playlist.data[u'skip']:
                        log.info(u">>")
                        skip = True
                        song = None  # don't scrobble
                        self.playlist.data[u"elapsed"] = 0
                        self.playlist.data[u"progress"] = 0
                        break

                    if self.playlist.data[u'status'] == u'stopped':
                        log.info(u".")
                        skip = True
                        song = None  # don't scrobble
                        self.playlist.data[u"elapsed"] = 0
                        break

                if not skip:
                    # increment the counter if we're not ffwding
                    self.playlist.next()
                else:
                    self.playlist.data[u'skip'] = False
                self.dirty_meta = True
            except error, e:
                if isinstance(e.args, tuple):
                    print "errno is %d" % e[0]
                    if e[0] == errno.EPIPE:
                        # remote peer disconnected
                        print "Detected remote disconnect"

                    elif e.errno == errno.ECONNRESET:
                        self.empty_scrobble_queue()
                        log.info(u"Client disconnected")
                    else:
                        log.info(u"Unknown socket error")
                        self.empty_scrobble_queue()
                        log.exception(errno.errorcode[e.errno])
                else:
                    print "socket error ", e
                self.request.close()
                self.playlist.data[u'status'] = 'stopped'
                break  # while
            except IOError, e:
                log.info("IO ERROR")
示例#10
0
    def run(self):
        # well this is just fugly.  call it "experimental"
        while Config.running:
            try:
                scrobble_item = self.queue.get(0)
                try:
                    song = scrobble_item.song
                    type = scrobble_item.type
                    error = scrobble_item.error
                    etime = scrobble_item.etime

                    try:
                        (tracknumber, artist, album,
                         track) = [escape(item) for item in song.tags]
                    except ValueError:
                        log.info("skipping scrobble for {} (bad tags)".format(
                            song.path))
                        continue

                    if type == NOW_PLAYING:
                        log.debug(u"scrobbling now playing %s %s %s" %
                                  (artist, track, album))
                        self.login()
                        scrobbler.now_playing(artist, track)
                        # now_playing auto flushes, apparently.  don't call
                        # flush here or it will throw an exception, which is not
                        # what we want.
                    elif type == PLAYED:
                        # See: http://exhuma.wicked.lu/projects/python/scrobbler/api/public/scrobbler-module.html#login
                        # if mimetype is wrong, length == 0
                        if song.length < 30:
                            log.warn(u"song length %s" % song.length)

                        # wait 60 seconds before re-trying
                        # submission
                        if error:
                            if (time.time() - etime) < 60:
                                break
                        log.debug(u"scrobbling played %s %s %s %s" %
                                  (artist, track, album, song.length))
                        self.login()
                        scrobbler.submit(
                            artist,
                            track,
                            int(
                                time.mktime(
                                    datetime.datetime.now().timetuple())),
                            source=escape(u'P'),
                            length=song.length,
                            album=album)
                        scrobbler.flush()
                except Exception as e:
                    log.exception(u"scrobble error: %s" % e)
                    # put it back
                    scrobble_item.error = True
                    scrobble_item.etime = time.time()
                    self.queue.put(scrobble_item)
            except Queue.Empty:
                pass

            # AS API enforced limit -- do not change.
            time.sleep(10)
示例#11
0
    def do_GET(self):
        # Handle well-behaved bots
        _path = self.path.strip()
        log.info(u"Request path: %s" % _path)
        if _path == u"/robots.txt":
            self.send(u"User-agent: *\nDisallow: /\n")
        elif _path != u"/":
            self.send_error(403, u"Bad request.\n")
        else:
            # path is /
            #
            # examine some headers

            # Client candidates:
            """ cmus """
            # GET / HTTP/1.0
            # Host: 0x7be.org
            # User-Agent: cmus/v2.3.2
            # Icy-MetaData: 1

            """ mplayer """
            # GET / HTTP/1.0
            # Host: 0x7be.org:18944
            # User-Agent: MPlayer/SVN-r31347-4.5.0
            # Icy-MetaData: 1
            # Connection: close

            # GET / HTTP/1.0
            # Accept: */*
            # User-Agent: NSPlayer/4.1.0.3856
            # Host: 0x7be.org:18944
            # Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}
            # Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=0:0,
            #           request-context=1,max-duration=0
            # Connection: Close

            """ squeezebox """
            # Connection: close
            # Cache-Control: no-cache
            # Accept: */*
            # Host: localhost:18944
            # User-Agent: iTunes/4.7.1 (Linux; N; Linux; i686-linux; EN;
            #           utf8) SqueezeCenter, Squeezebox Server/7.4.1/28947
            # Icy-Metadata: 1

            H, icy_client = self.headers, False
            try:
                icy_client = (int(H[u'icy-metadata']) == 1)
            except KeyError, e:
                log.error(u"non-icy client:  %s" % e)
                log.error(self.address_string())

            if not icy_client:
                self.send_response(400, u"Bad client.\n Try http://cmus.sourceforge.net/\n")
                return False

            user_agent = None
            try:                user_agent = H[u'user-agent']
            except KeyError, e: log.exception(u"Couldn't get user agent.")
            if user_agent:      log.info(u"User-Agent:  %s" % user_agent)

            self.do_HEAD( icy_client )
            try:
                Streamer( self.request, self.server.port ).stream( icy_client )
            except IOError, e:
                if e.errno != errno.ECONNRESET:
                    log.warn("streamer hung up")
示例#12
0
class ServerRequestHandler(BaseHTTPRequestHandler):
    def do_HEAD(self, icy_client):
        #if icy_client:
        self.send_response(200, u"ICY")
        # fixme verbose
        headers = {
            u'icy-notice1': Config.notice_1,
            u'icy-notice2': Config.notice_2,
            u'icy-name': Config.icy_name,
            u'icy-genre': Config.icy_genre,
            u'icy-url': Config.icy_url,
            u'icy-pub': Config.icy_pub,
            #'icy-br'        : 128,
            u'icy-metaint': Config.icy_metaint,
            u'content-type': Config.content_type
        }
        [self.send_header(k, v) for k, v, in headers.iteritems()]
        self.end_headers()

    def do_POST(self):
        time.sleep(6000)

    def do_GET(self):
        # Handle well-behaved bots
        _path = self.path.strip()
        log.info(u"Request path: %s" % _path)
        if _path == u"/robots.txt":
            self.send(u"User-agent: *\nDisallow: /\n")
        elif _path != u"/":
            self.send_error(403, u"Bad request.\n")
        else:
            # path is /
            #
            # examine some headers

            # Client candidates:
            """ cmus """
            # GET / HTTP/1.0
            # Host: 0x7be.org
            # User-Agent: cmus/v2.3.2
            # Icy-MetaData: 1
            """ mplayer """
            # GET / HTTP/1.0
            # Host: 0x7be.org:18944
            # User-Agent: MPlayer/SVN-r31347-4.5.0
            # Icy-MetaData: 1
            # Connection: close

            # GET / HTTP/1.0
            # Accept: */*
            # User-Agent: NSPlayer/4.1.0.3856
            # Host: 0x7be.org:18944
            # Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}
            # Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=0:0,
            #           request-context=1,max-duration=0
            # Connection: Close
            """ squeezebox """
            # Connection: close
            # Cache-Control: no-cache
            # Accept: */*
            # Host: localhost:18944
            # User-Agent: iTunes/4.7.1 (Linux; N; Linux; i686-linux; EN;
            #           utf8) SqueezeCenter, Squeezebox Server/7.4.1/28947
            # Icy-Metadata: 1

            H, icy_client = self.headers, False
            try:
                icy_client = (int(H[u'icy-metadata']) == 1)
            except KeyError, e:
                log.error(u"non-icy client:  %s" % e)
                log.error(self.address_string())

            if not icy_client:
                self.send_response(
                    400, u"Bad client.\n Try http://cmus.sourceforge.net/\n")
                return False

            user_agent = None
            try:
                user_agent = H[u'user-agent']
            except KeyError, e:
                log.exception(u"Couldn't get user agent.")
            if user_agent: log.info(u"User-Agent:  %s" % user_agent)

            self.do_HEAD(icy_client)
            try:
                Streamer(self.request, self.server.port).stream(icy_client)
            except IOError, e:
                if e.errno != errno.ECONNRESET:
                    log.warn("streamer hung up")
示例#13
0
            H, icy_client = self.headers, False
            try:
                icy_client = (int(H[u'icy-metadata']) == 1)
            except KeyError, e:
                log.error(u"non-icy client:  %s" % e)
                log.error(self.address_string())

            if not icy_client:
                self.send_response(
                    400, u"Bad client.\n Try http://cmus.sourceforge.net/\n")
                return False

            user_agent = None
            try:
                user_agent = H[u'user-agent']
            except KeyError, e:
                log.exception(u"Couldn't get user agent.")
            if user_agent: log.info(u"User-Agent:  %s" % user_agent)

            self.do_HEAD(icy_client)
            try:
                Streamer(self.request, self.server.port).stream(icy_client)
            except IOError, e:
                if e.errno != errno.ECONNRESET:
                    log.warn("streamer hung up")
            except EOFError:
                log.warn("streamer hung up")

        return 0