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)
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)
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
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"")
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)
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)
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")
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")
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)
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")
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")
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