class WebServer(object): """ Starts Tornado web server in a separate thread """ def __init__(self, util, peppy): """ Initializer. Start web server in separate thread :param util: utility object contains configuration settings :param peppy: the reference to the root object """ self.util = util self.lock = RLock() self.config = util.config self.config_class = util.config_class self.peppy = peppy self.web_clients = [] self.player_listeners = [] self.json_factory = JsonFactory(util, peppy) thread = Thread(target=self.start_web_server) thread.daemon = True thread.start() def start_web_server(self): """ Prepare request handlers and start server """ root = os.getcwd() app = Application([ (r"/()", StaticFileHandler, {"path": root, "default_filename": "index.html"}), (r"/web/client/(.*)", StaticFileHandler, {"path": root + "/web/client"}), (r"/font/(.*)", StaticFileHandler, {"path": root + "/font"}), (r"/icon/(.*)", StaticFileHandler, {"path": root + "/icons"}), (r"/flag/(.*)", StaticFileHandler, {"path": root + "/languages"}), (r"/ws", WebSocketHandler, {"redraw_web_ui": self.redraw_web_ui, "web_clients": self.web_clients}), (r"/config/()", StaticFileHandler, {"path": root + "/web/client/config", "default_filename": "index.html"}), (r"/config/icon/(.*)", StaticFileHandler, {"path": root + "/languages"}), (r"/config/default/(.*)", StaticFileHandler, {"path": root + "/icons"}), (r"/static/js/(.*)", StaticFileHandler, {"path": root + "/web/client/config/static/js"}), (r"/static/css/(.*)", StaticFileHandler, {"path": root + "/web/client/config/static/css"}), (r"/static/media/(.*)", StaticFileHandler, {"path": root + "/web/client/config/static/media"}), (r"/parameters", ParametersHandler, {"config_class": self.config_class}), (r"/players", PlayersHandler, {"config_class": self.config_class}), (r"/savers", ScreensaversHandler, {"config": self.config}), (r"/podcasts", PodcastsHandler, {"util": self.util}), (r"/streams", StreamsHandler, {"util": self.util}), (r"/streamimage/(.*)", StaticFileHandler, {"path": root + "/streams"}), (r"/playlists", PlaylistsHandler, {"util": self.util}), (r"/labels", LabelsHandler, {"util": self.util}), (r"/command/(.*)", CommandHandler, {"peppy": self.peppy}), (r"/upload", UploadHandler, {"path": root}) ]) if self.config[WEB_SERVER][HTTPS]: http_server = tornado.httpserver.HTTPServer(app, ssl_options={"certfile": "cert", "keyfile": "key"}) else: http_server = tornado.httpserver.HTTPServer(app) port = self.config[WEB_SERVER][HTTP_PORT] http_server.listen(port) logging.debug("Web Server Started") tornado.ioloop.IOLoop.current().start() def update_web_ui(self, state): """ Update Web UI component :param state: object with Web UI component as event_origin attribute """ if not (state and getattr(state, "event_origin", None) != None): return j = self.json_factory.container_to_json(state.event_origin) self.send_json_to_web_ui(j) def update_player_listeners(self, state=None): """ Update player listeners """ for c in self.player_listeners: self.send_json_to_web_ui(self.json_factory.container_to_json(c)) def redraw_web_ui(self, state=None): """ Redraw the whole screen in web UI """ self.send_json_to_web_ui(self.screen_to_json()) def start_screensaver_to_json(self, state=None): """ Send command to web UI to start screensaver """ if state == None: self.send_json_to_web_ui(self.json_factory.start_screensaver_to_json()) else: name = self.config[SCREENSAVER][NAME] screen = state.screen command = self.json_factory.screen_to_json(name, screen) self.send_json_to_web_ui(command) def start_time_control_to_json(self, state=None): """ Send start time control command to all web clients """ j = self.json_factory.file_player_start_to_json() self.send_json_to_web_ui(j) def stop_time_control_to_json(self, state=None): """ Send stop time control command to all web clients """ j = self.json_factory.file_player_stop_to_json() self.send_json_to_web_ui(j) def stop_screensaver_to_json(self, state=None): """ Send command to web UI to stop screensaver """ self.send_json_to_web_ui(self.json_factory.stop_screensaver_to_json()) def screen_to_json(self): """ Convert current screen to JSON objects :return: list of JSON objects representing current screen """ current_screen = self.peppy.current_screen screen = self.peppy.screens[current_screen] if not screen.visible: if self.peppy.screensaver_dispatcher.saver_running: screen = self.peppy.screensaver_dispatcher.current_screensaver current_screen = self.peppy.screensaver_dispatcher.current_screensaver.name if current_screen not in WEB_SAVERS: current_screen = KEY_ABOUT screen = self.peppy.screens[KEY_ABOUT] screen.visible = True return self.json_factory.screen_to_json(current_screen, screen) def station_menu_to_json(self, state): """ Convert station menu object into Json object :param menu: the station menu object :return: Json object """ self.send_json_to_web_ui(self.screen_to_json()) def title_to_json(self, title): """ Convert screen title to Json object :param title: screen title object """ j = self.json_factory.title_to_json(title) self.send_json_to_web_ui(j) def send_json_to_web_ui(self, j): """ Send provided Json object to all web clients "param j": Json object to send """ for c in self.web_clients: e = json.dumps(j).encode(encoding="utf-8") ioloop = tornado.ioloop.IOLoop.instance() ioloop.add_callback(c.write_message, e) def add_player_listener(self, listener): """ Add player web listener :param listener: player listener """ if listener not in self.player_listeners: self.player_listeners.append(listener) def shutdown(self): """ Shutdown Web Server """ ioloop = tornado.ioloop.IOLoop.instance() ioloop.add_callback(ioloop.stop)
class WebServer(object): """ Starts simple HTTPServer in a separate thread """ def __init__(self, util, peppy): """ Initializer :param util: utility object contains configuration settings :param peppy: the reference to the root object """ self.config = util.config self.peppy = peppy self.jason_factory = JsonFactory(util, peppy) self.web_server_thread = threading.Thread(target=self.start) self.web_server_thread.start() def get_ip(self): """ Returns current IP address """ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.connect(('10.255.255.255', 0)) ip = s.getsockname()[0] except: ip = '127.0.0.1' finally: s.close() return ip def start(self): """ Prepares request handler and starts web server """ host = self.get_ip() port = self.config[WEB_SERVER][HTTP_PORT] handler = RequestHandler handler.screen_to_json = self.screen_to_json self.create_screen = handler.create_screen = web.server.requesthandler.create_screen handler.title_to_json = self.title_to_json self.title_change = handler.update_title = web.server.requesthandler.update_title handler.volume_to_json = self.volume_to_json self.volume_change = handler.update_volume = web.server.requesthandler.update_volume handler.genre_button_to_json = self.genre_button_to_json self.genre_button_pressed = handler.update_genre_button = web.server.requesthandler.update_genre_button handler.home_button_to_json = self.home_button_to_json self.home_button_pressed = handler.update_home_button = web.server.requesthandler.update_home_button handler.left_button_to_json = self.left_button_to_json self.left_button_pressed = handler.update_left_button = web.server.requesthandler.update_left_button handler.page_down_button_to_json = self.page_down_button_to_json self.page_down_button_pressed = handler.update_page_down_button = web.server.requesthandler.update_page_down_button handler.right_button_to_json = self.right_button_to_json self.right_button_pressed = handler.update_right_button = web.server.requesthandler.update_right_button handler.page_up_button_to_json = self.page_up_button_to_json self.page_up_button_pressed = handler.update_page_up_button = web.server.requesthandler.update_page_up_button handler.station_menu_to_json = self.station_menu_to_json self.update_station_menu = handler.update_station_menu = web.server.requesthandler.update_station_menu handler.genre_menu_to_json = self.genre_menu_to_json self.update_genre_menu = handler.update_genre_menu = web.server.requesthandler.update_genre_menu handler.home_menu_to_json = self.home_menu_to_json self.update_home_menu = handler.update_home_menu = web.server.requesthandler.update_home_menu handler.language_menu_to_json = self.language_menu_to_json self.update_language_menu = handler.update_language_menu = web.server.requesthandler.update_language_menu handler.saver_screen_to_json = self.saver_screen_to_json self.update_saver_screen = handler.update_saver_menu = web.server.requesthandler.update_saver_screen handler.about_screen_to_json = self.about_screen_to_json self.update_about_screen = handler.update_about_screen = web.server.requesthandler.update_about_screen self.mode_listener = handler.mode_listener = web.server.requesthandler.mode_listener handler.play_button_to_json = self.play_button_to_json self.play_button_pressed = handler.update_play_button = web.server.requesthandler.update_play_button handler.shutdown_button_to_json = self.shutdown_button_to_json self.shutdown_button_pressed = handler.update_shutdown_button = web.server.requesthandler.update_shutdown_button handler.start_screensaver_to_json = self.start_screensaver_to_json handler.stop_screensaver_to_json = self.stop_screensaver_to_json self.start_screensaver = handler.start_screensaver = web.server.requesthandler.start_screensaver self.stop_screensaver = handler.stop_screensaver = web.server.requesthandler.stop_screensaver self.web_server = HTTPServer((host, int(port)), handler) logging.debug("Web Server Started at %s:%s", host, port) try: self.web_server.serve_forever() except: pass def get_station_screen(self): """ Return Station Screen :return: the reference to the Station Screen """ return self.peppy.screens["stations"] def get_genre_screen(self): """ Return Genre Screen :return: the reference to the Genre Screen """ return self.peppy.screens["genres"] def get_home_screen(self): """ Return Home Screen :return: the reference to the Home Screen """ return self.peppy.screens["home"] def get_language_screen(self): """ Return Language Screen :return: the reference to the Language Screen """ return self.peppy.screens["language"] def get_saver_screen(self): """ Return Screensaver Screen :return: the reference to the Screensaver Screen """ return self.peppy.screens["saver"] def get_about_screen(self): """ Return About Screen :return: the reference to the About Screen """ return self.peppy.screens["about"] def screen_to_json(self): """ Convert current screen to JSON objects :return: list of JSON objects representing current screen """ if self.peppy.screensaver_dispatcher.saver_running: self.peppy.screensaver_dispatcher.cancel_screensaver() self.peppy.screensaver_dispatcher.restart_dispatcher_thread() current_screen = self.peppy.current_screen screen = self.peppy.screens[current_screen] return self.jason_factory.screen_to_json(current_screen, screen) def title_to_json(self): """ Convert title object into JSON object :return: JSON object """ return self.jason_factory.title_to_json(self.get_station_screen().screen_title) def volume_to_json(self): """ Convert volume object into JSON object :return: JSON object """ return self.jason_factory.container_to_json(self.get_station_screen().volume) def genre_button_to_json(self): """ Convert genre button into JSON object :return: JSON object """ return self.jason_factory.container_to_json(self.get_station_screen().genres_button) def home_button_to_json(self): """ Convert home button into JSON object :return: JSON object """ return self.jason_factory.container_to_json(self.get_station_screen().home_button) def left_button_to_json(self): """ Convert left button into JSON object :return: JSON object """ return self.jason_factory.container_to_json(self.get_station_screen().left_button) def page_down_button_to_json(self): """ Convert page down button into JSON object :return: JSON object """ return self.jason_factory.container_to_json(self.get_station_screen().page_down_button) def right_button_to_json(self): """ Convert right button into JSON object :return: JSON object """ return self.jason_factory.container_to_json(self.get_station_screen().right_button) def page_up_button_to_json(self): """ Convert page up button into JSON object :return: JSON object """ return self.jason_factory.container_to_json(self.get_station_screen().page_up_button) def station_menu_to_json(self): """ Convert station menu into JSON object :return: JSON object """ return self.jason_factory.station_menu_to_json(self.get_station_screen().station_menu) def play_button_to_json(self): """ Convert play button into JSON object :return: JSON object """ return self.jason_factory.container_to_json(self.get_station_screen().play_button) def shutdown_button_to_json(self): """ Convert shutdown button into JSON object :return: JSON object """ return self.jason_factory.container_to_json(self.get_station_screen().shutdown_button) def genre_menu_to_json(self): """ Convert genre menu into JSON object :return: JSON object """ return self.jason_factory.genre_menu_to_json(self.get_genre_screen().genre_menu) def home_menu_to_json(self): """ Convert home menu into JSON object :return: JSON object """ return self.jason_factory.home_menu_to_json(self.get_home_screen().home_menu) def language_menu_to_json(self): """ Convert language menu into JSON object :return: JSON object """ return self.jason_factory.language_menu_to_json(self.get_language_screen().language_menu) def saver_screen_to_json(self): """ Convert screensaver screen into JSON object :return: JSON object """ return self.jason_factory.saver_screen_to_json(self.get_saver_screen()) def about_screen_to_json(self): """ Convert about screen into JSON object :return: JSON object """ return self.jason_factory.about_screen_to_json(self.get_about_screen()) def start_screensaver_to_json(self): """ Convert start screensaver event into JSON object :return: JSON object """ return self.jason_factory.start_screensaver_to_json() def stop_screensaver_to_json(self): """ Convert stop screensaver event into JSON object :return: JSON object """ return self.jason_factory.stop_screensaver_to_json() def add_station_screen_web_listeners(self, stations): """ Add web listeners to station screen components :param stations: the stations screen """ stations.screen_title.add_listener(self.title_change) stations.volume.add_slide_listener(self.volume_change) stations.volume.add_knob_listener(self.volume_change) stations.volume.add_press_listener(self.volume_change) stations.volume.add_motion_listener(self.volume_change) stations.genres_button.add_press_listener(self.genre_button_pressed) stations.genres_button.add_release_listener(self.create_screen) stations.home_button.add_press_listener(self.home_button_pressed) stations.home_button.add_release_listener(self.create_screen) stations.station_menu.add_menu_click_listener(self.update_station_menu) stations.station_menu.add_menu_click_listener(self.left_button_pressed) stations.station_menu.add_menu_click_listener(self.right_button_pressed) stations.station_menu.add_menu_click_listener(self.page_down_button_pressed) stations.station_menu.add_menu_click_listener(self.page_up_button_pressed) stations.station_menu.add_mode_listener(self.mode_listener) stations.left_button.add_press_listener(self.left_button_pressed) stations.left_button.add_release_listener(self.left_button_pressed) stations.left_button.add_release_listener(self.update_station_menu) stations.left_button.add_release_listener(self.right_button_pressed) stations.page_down_button.add_press_listener(self.page_down_button_pressed) stations.page_down_button.add_release_listener(self.page_down_button_pressed) stations.page_down_button.add_release_listener(self.update_station_menu) stations.page_down_button.add_release_listener(self.page_up_button_pressed) stations.right_button.add_press_listener(self.right_button_pressed) stations.right_button.add_release_listener(self.right_button_pressed) stations.right_button.add_release_listener(self.update_station_menu) stations.right_button.add_release_listener(self.left_button_pressed) stations.page_up_button.add_press_listener(self.page_up_button_pressed) stations.page_up_button.add_release_listener(self.page_up_button_pressed) stations.page_up_button.add_release_listener(self.update_station_menu) stations.page_up_button.add_release_listener(self.page_down_button_pressed) stations.play_button.add_press_listener(self.play_button_pressed) stations.play_button.add_release_listener(self.play_button_pressed) stations.shutdown_button.add_press_listener(self.shutdown_button_pressed) stations.shutdown_button.add_release_listener(self.shutdown_button_pressed) stations.shutdown_button.add_cancel_listener(self.shutdown_button_pressed) def add_genre_screen_web_listeners(self, genres): """ Add web listeners to genre screen components :param genres: the genres screen """ genres.genre_menu.add_listener(self.create_screen) genres.genre_menu.add_move_listener(self.update_genre_menu) def add_home_screen_web_listeners(self, home): """ Add web listeners to home screen components :param home: the home screen """ home.home_menu.add_listener(self.create_screen) home.home_menu.add_move_listener(self.update_home_menu) def add_language_screen_web_listeners(self, language): """ Add web listeners to language screen components :param language: the language screen """ language.language_menu.add_listener(self.create_screen) language.language_menu.add_move_listener(self.update_language_menu) def add_saver_screen_web_listeners(self, saver): """ Add web listeners to screensaver screen components :param saver: the screensaver screen """ saver.saver_menu.add_listener(self.create_screen) saver.delay_menu.add_listener(self.create_screen) saver.saver_menu.add_move_listener(self.update_saver_screen) saver.delay_menu.add_move_listener(self.update_saver_screen) def add_about_screen_web_listeners(self, about): """ Add web listeners to about screen :param about: the about screen """ about.add_listener(self.create_screen) def add_screensaver_web_listener(self, screensaver_dispatcher): """ Add web listeners to screensaver start and stop events :param screensaver_dispatcher: the screensaver dispatcher """ screensaver_dispatcher.add_start_listener(self.start_screensaver) screensaver_dispatcher.add_stop_listener(self.stop_screensaver) def shutdown(self): """ Shutdown Web Server """ self.web_server.socket.close()
class WebServer(object): """ Starts Tornado web server in a separate thread """ def __init__(self, util, peppy): """ Initializer. Start web server in separate thread :param util: utility object contains configuration settings :param peppy: the reference to the root object """ self.lock = RLock() self.config = util.config self.peppy = peppy self.web_clients = [] self.player_listeners = [] self.json_factory = JsonFactory(util, peppy) thread = Thread(target=self.start_web_server) thread.daemon = True thread.start() def start_web_server(self): """ Prepare request handlers and start server """ root = os.getcwd() index = "index.html" host = socket.gethostbyname(socket.gethostname()) port = self.config[WEB_SERVER][HTTP_PORT] if tornado.version.startswith("5"): import asyncio asyncio.set_event_loop(asyncio.new_event_loop()) indexHandler = (r"/()", tornado.web.StaticFileHandler, { "path": root, "default_filename": "index.html" }) staticHandler = (r"/web/client/(.*)", tornado.web.StaticFileHandler, { "path": root + "/web/client" }) fontHandler = (r"/font/(.*)", tornado.web.StaticFileHandler, { "path": root + "/font" }) d = { "redraw_web_ui": self.redraw_web_ui, "web_clients": self.web_clients } webSocketHandler = (r"/ws", WebSocketHandler, d) application = tornado.web.Application( [indexHandler, staticHandler, fontHandler, webSocketHandler]) http_server = tornado.httpserver.HTTPServer(application) http_server.listen(port) logging.debug("Web Server Started at %s:%s", host, port) tornado.ioloop.IOLoop.current().start() def update_web_ui(self, state): """ Update Web UI component :param state: object with Web UI component as event_origin attribute """ if not (state and state.event_origin): return j = self.json_factory.container_to_json(state.event_origin) self.send_json_to_web_ui(j) def update_player_listeners(self, state=None): """ Update player listeners """ for c in self.player_listeners: self.send_json_to_web_ui(self.json_factory.container_to_json(c)) def redraw_web_ui(self, state=None): """ Redraw the whole screen in web UI """ self.send_json_to_web_ui(self.screen_to_json()) def start_screensaver_to_json(self, state=None): """ Send command to web UI to start screensaver """ self.send_json_to_web_ui(self.json_factory.start_screensaver_to_json()) def start_time_control_to_json(self, state=None): """ Send start time control command to all web clients """ j = self.json_factory.file_player_start_to_json() self.send_json_to_web_ui(j) def stop_time_control_to_json(self, state=None): """ Send stop time control command to all web clients """ j = self.json_factory.file_player_stop_to_json() self.send_json_to_web_ui(j) def stop_screensaver_to_json(self, state=None): """ Send command to web UI to stop screensaver """ self.send_json_to_web_ui(self.json_factory.stop_screensaver_to_json()) def screen_to_json(self): """ Convert current screen to JSON objects :return: list of JSON objects representing current screen """ current_screen = self.peppy.current_screen screen = self.peppy.screens[current_screen] if not screen.visible: current_screen = KEY_ABOUT screen = self.peppy.screens[KEY_ABOUT] screen.visible = True return self.json_factory.screen_to_json(current_screen, screen) def station_menu_to_json(self, state): """ Convert station menu object into Json object :param menu: the station menu object :return: Json object """ self.send_json_to_web_ui(self.screen_to_json()) def title_to_json(self, title): """ Convert screen title to Json object :param title: screen title object """ j = self.json_factory.title_to_json(title) self.send_json_to_web_ui(j) def send_json_to_web_ui(self, j): """ Send provided Json object to all web clients "param j" Json object to send """ for c in self.web_clients: e = json.dumps(j).encode(encoding="utf-8") ioloop = tornado.ioloop.IOLoop.instance() ioloop.add_callback(c.write_message, e) def add_player_listener(self, listener): """ Add player web listener :param listener: player listener """ if listener not in self.player_listeners: self.player_listeners.append(listener) def shutdown(self): """ Shutdown Web Server """ ioloop = tornado.ioloop.IOLoop.instance() ioloop.add_callback(ioloop.stop)