<s> """<STR_LIT>""" <EOL> from collections import namedtuple <EOL> from . . config import APP_MEDIA_RECEIVER <EOL> from . import BaseController <EOL> STREAM_TYPE_UNKNOWN = "<STR_LIT>" <EOL> STREAM_TYPE_BUFFERED = "<STR_LIT>" <EOL> STREAM_TYPE_LIVE = "<STR_LIT>" <EOL> MEDIA_PLAYER_STATE_PLAYING = "<STR_LIT>" <EOL> MEDIA_PLAYER_STATE_PAUSED = "<STR_LIT>" <EOL> MEDIA_PLAYER_STATE_IDLE = "<STR_LIT>" <EOL> MEDIA_PLAYER_STATE_UNKNOWN = "<STR_LIT>" <EOL> MESSAGE_TYPE = '<STR_LIT:type>' <EOL> TYPE_GET_STATUS = "<STR_LIT>" <EOL> TYPE_MEDIA_STATUS = "<STR_LIT>" <EOL> TYPE_PLAY = "<STR_LIT>" <EOL> TYPE_PAUSE = "<STR_LIT>" <EOL> TYPE_STOP = "<STR_LIT>" <EOL> TYPE_LOAD = "<STR_LIT>" <EOL> TYPE_SEEK = "<STR_LIT>" <EOL> TYPE_EDIT_TRACKS_INFO = "<STR_LIT>" <EOL> METADATA_TYPE_GENERIC = <NUM_LIT:0> <EOL> METADATA_TYPE_TVSHOW = <NUM_LIT:1> <EOL> METADATA_TYPE_MOVIE = <NUM_LIT:2> <EOL> METADATA_TYPE_MUSICTRACK = <NUM_LIT:3> <EOL> METADATA_TYPE_PHOTO = <NUM_LIT:4> <EOL> CMD_SUPPORT_PAUSE = <NUM_LIT:1> <EOL> CMD_SUPPORT_SEEK = <NUM_LIT:2> <EOL> CMD_SUPPORT_STREAM_VOLUME = <NUM_LIT:4> <EOL> CMD_SUPPORT_STREAM_MUTE = <NUM_LIT:8> <EOL> CMD_SUPPORT_SKIP_FORWARD = <NUM_LIT:16> <EOL> CMD_SUPPORT_SKIP_BACKWARD = <NUM_LIT:32> <EOL> MediaImage = namedtuple ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> class MediaStatus ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . current_time = <NUM_LIT:0> <EOL> self . content_id = None <EOL> self . content_type = None <EOL> self . duration = None <EOL> self . stream_type = STREAM_TYPE_UNKNOWN <EOL> self . idle_reason = None <EOL> self . media_session_id = None <EOL> self . playback_rate = <NUM_LIT:1> <EOL> self . player_state = MEDIA_PLAYER_STATE_UNKNOWN <EOL> self . supported_media_commands = <NUM_LIT:0> <EOL> self . volume_level = <NUM_LIT:1> <EOL> self . volume_muted = False <EOL> self . media_custom_data = { } <EOL> self . media_metadata = { } <EOL> self . subtitle_tracks = { } <EOL> @ property <EOL> def metadata_type ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . media_metadata . get ( '<STR_LIT>' ) <EOL> @ property <EOL> def player_is_playing ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . player_state == MEDIA_PLAYER_STATE_PLAYING <EOL> @ property <EOL> def player_is_paused ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . player_state == MEDIA_PLAYER_STATE_PAUSED <EOL> @ property <EOL> def player_is_idle ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . player_state == MEDIA_PLAYER_STATE_IDLE <EOL> @ property <EOL> def media_is_generic ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . metadata_type == METADATA_TYPE_GENERIC <EOL> @ property <EOL> def media_is_tvshow ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . metadata_type == METADATA_TYPE_TVSHOW <EOL> @ property <EOL> def media_is_movie ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . metadata_type == METADATA_TYPE_MOVIE <EOL> @ property <EOL> def media_is_musictrack ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . metadata_type == METADATA_TYPE_MUSICTRACK <EOL> @ property <EOL> def media_is_photo ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . metadata_type == METADATA_TYPE_PHOTO <EOL> @ property <EOL> def stream_type_is_buffered ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . stream_type == STREAM_TYPE_BUFFERED <EOL> @ property <EOL> def stream_type_is_live ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . stream_type == STREAM_TYPE_LIVE <EOL> @ property <EOL> def title ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . media_metadata . get ( '<STR_LIT:title>' ) <EOL> @ property <EOL> def series_title ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . media_metadata . get ( '<STR_LIT>' ) <EOL> @ property <EOL> def season ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . media_metadata . get ( '<STR_LIT>' ) <EOL> @ property <EOL> def episode ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . media_metadata . get ( '<STR_LIT>' ) <EOL> @ property <EOL> def artist ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . media_metadata . get ( '<STR_LIT>' ) <EOL> @ property <EOL> def album_name ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . media_metadata . get ( '<STR_LIT>' ) <EOL> @ property <EOL> def album_artist ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . media_metadata . get ( '<STR_LIT>' ) <EOL> @ property <EOL> def track ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . media_metadata . get ( '<STR_LIT>' ) <EOL> @ property <EOL> def images ( self ) : <EOL> """<STR_LIT>""" <EOL> return [ <EOL> MediaImage ( item . get ( '<STR_LIT:url>' ) , item . get ( '<STR_LIT>' ) , item . get ( '<STR_LIT:width>' ) ) <EOL> for item in self . media_metadata . get ( '<STR_LIT>' , [ ] ) <EOL> ] <EOL> @ property <EOL> def supports_pause ( self ) : <EOL> """<STR_LIT>""" <EOL> return bool ( self . supported_media_commands & CMD_SUPPORT_PAUSE ) <EOL> @ property <EOL> def supports_seek ( self ) : <EOL> """<STR_LIT>""" <EOL> return bool ( self . supported_media_commands & CMD_SUPPORT_SEEK ) <EOL> @ property <EOL> def supports_stream_volume ( self ) : <EOL> """<STR_LIT>""" <EOL> return bool ( self . supported_media_commands & CMD_SUPPORT_STREAM_VOLUME ) <EOL> @ property <EOL> def supports_stream_mute ( self ) : <EOL> """<STR_LIT>""" <EOL> return bool ( self . supported_media_commands & CMD_SUPPORT_STREAM_MUTE ) <EOL> @ property <EOL> def supports_skip_forward ( self ) : <EOL> """<STR_LIT>""" <EOL> return bool ( self . supported_media_commands & CMD_SUPPORT_SKIP_FORWARD ) <EOL> @ property <EOL> def supports_skip_backward ( self ) : <EOL> """<STR_LIT>""" <EOL> return bool ( self . supported_media_commands & CMD_SUPPORT_SKIP_BACKWARD ) <EOL> def update ( self , data ) : <EOL> """<STR_LIT>""" <EOL> if len ( data . get ( '<STR_LIT:status>' , [ ] ) ) == <NUM_LIT:0> : <EOL> return <EOL> status_data = data [ '<STR_LIT:status>' ] [ <NUM_LIT:0> ] <EOL> media_data = status_data . get ( '<STR_LIT>' ) or { } <EOL> volume_data = status_data . get ( '<STR_LIT>' , { } ) <EOL> self . current_time = status_data . get ( '<STR_LIT>' , self . current_time ) <EOL> self . content_id = media_data . get ( '<STR_LIT>' , self . content_id ) <EOL> self . content_type = media_data . get ( '<STR_LIT>' , self . content_type ) <EOL> self . duration = media_data . get ( '<STR_LIT>' , self . duration ) <EOL> self . stream_type = media_data . get ( '<STR_LIT>' , self . stream_type ) <EOL> self . idle_reason = status_data . get ( '<STR_LIT>' , self . idle_reason ) <EOL> self . media_session_id = status_data . get ( <EOL> '<STR_LIT>' , self . media_session_id ) <EOL> self . playback_rate = status_data . get ( <EOL> '<STR_LIT>' , self . playback_rate ) <EOL> self . player_state = status_data . get ( '<STR_LIT>' , self . player_state ) <EOL> self . supported_media_commands = status_data . get ( <EOL> '<STR_LIT>' , self . supported_media_commands ) <EOL> self . volume_level = volume_data . get ( '<STR_LIT>' , self . volume_level ) <EOL> self . volume_muted = volume_data . get ( '<STR_LIT>' , self . volume_muted ) <EOL> self . media_custom_data = media_data . get ( <EOL> '<STR_LIT>' , self . media_custom_data ) <EOL> self . media_metadata = media_data . get ( '<STR_LIT>' , self . media_metadata ) <EOL> self . subtitle_tracks = media_data . get ( '<STR_LIT>' , self . subtitle_tracks ) <EOL> def __repr__ ( self ) : <EOL> info = { <EOL> '<STR_LIT>' : self . metadata_type , <EOL> '<STR_LIT:title>' : self . title , <EOL> '<STR_LIT>' : self . series_title , <EOL> '<STR_LIT>' : self . season , <EOL> '<STR_LIT>' : self . episode , <EOL> '<STR_LIT>' : self . artist , <EOL> '<STR_LIT>' : self . album_name , <EOL> '<STR_LIT>' : self . album_artist , <EOL> '<STR_LIT>' : self . track , <EOL> '<STR_LIT>' : self . subtitle_tracks , <EOL> '<STR_LIT>' : self . images , <EOL> '<STR_LIT>' : self . supports_pause , <EOL> '<STR_LIT>' : self . supports_seek , <EOL> '<STR_LIT>' : self . supports_stream_volume , <EOL> '<STR_LIT>' : self . supports_stream_mute , <EOL> '<STR_LIT>' : self . supports_skip_forward , <EOL> '<STR_LIT>' : self . supports_skip_backward , <EOL> } <EOL> info . update ( self . __dict__ ) <EOL> return '<STR_LIT>' . format ( info ) <EOL> class MediaController ( BaseController ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> super ( MediaController , self ) . __init__ ( <EOL> "<STR_LIT>" ) <EOL> self . media_session_id = <NUM_LIT:0> <EOL> self . status = MediaStatus ( ) <EOL> self . _status_listeners = [ ] <EOL> def channel_connected ( self ) : <EOL> """<STR_LIT>""" <EOL> self . update_status ( ) <EOL> def channel_disconnected ( self ) : <EOL> """<STR_LIT>""" <EOL> self . status = MediaStatus ( ) <EOL> self . _fire_status_changed ( ) <EOL> def receive_message ( self , message , data ) : <EOL> """<STR_LIT>""" <EOL> if data [ MESSAGE_TYPE ] == TYPE_MEDIA_STATUS : <EOL> self . _process_media_status ( data ) <EOL> return True <EOL> else : <EOL> return False <EOL> def register_status_listener ( self , listener ) : <EOL> """<STR_LIT>""" <EOL> self . _status_listeners . append ( listener ) <EOL> def update_status ( self , blocking = False ) : <EOL> """<STR_LIT>""" <EOL> self . send_message ( { MESSAGE_TYPE : TYPE_GET_STATUS } , <EOL> wait_for_response = blocking ) <EOL> def _send_command ( self , command ) : <EOL> """<STR_LIT>""" <EOL> if self . status is None or self . status . media_session_id is None : <EOL> return <EOL> command [ '<STR_LIT>' ] = self . status . media_session_id <EOL> self . send_message ( command , inc_session_id = True ) <EOL> @ property <EOL> def is_playing ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . status is not None and self . status . player_is_playing <EOL> @ property <EOL> def is_paused ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . status is not None and self . status . player_is_paused <EOL> @ property <EOL> def is_idle ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . status is not None and self . status . player_is_idle <EOL> @ property <EOL> def title ( self ) : <EOL> """<STR_LIT>""" <EOL> return None if not self . status else self . status . title <EOL> @ property <EOL> def thumbnail ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . status : <EOL> return None <EOL> images = self . status . images <EOL> return images [ <NUM_LIT:0> ] . url if images and len ( images ) > <NUM_LIT:0> else None <EOL> def play ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _send_command ( { MESSAGE_TYPE : TYPE_PLAY } ) <EOL> def pause ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _send_command ( { MESSAGE_TYPE : TYPE_PAUSE } ) <EOL> def stop ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _send_command ( { MESSAGE_TYPE : TYPE_STOP } ) <EOL> def rewind ( self ) : <EOL> """<STR_LIT>""" <EOL> self . seek ( <NUM_LIT:0> ) <EOL> def skip ( self ) : <EOL> """<STR_LIT>""" <EOL> self . seek ( int ( self . status . duration ) - <NUM_LIT:5> ) <EOL> def seek ( self , position ) : <EOL> """<STR_LIT>""" <EOL> self . _send_command ( { MESSAGE_TYPE : TYPE_SEEK , <EOL> "<STR_LIT>" : position , <EOL> "<STR_LIT>" : "<STR_LIT>" } ) <EOL> def enable_subtitle ( self , track_id ) : <EOL> """<STR_LIT>""" <EOL> self . _send_command ( { <EOL> MESSAGE_TYPE : TYPE_EDIT_TRACKS_INFO , <EOL> "<STR_LIT>" : [ track_id ] <EOL> } ) <EOL> def disable_subtitle ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _send_command ( { <EOL> MESSAGE_TYPE : TYPE_EDIT_TRACKS_INFO , <EOL> "<STR_LIT>" : [ ] <EOL> } ) <EOL> def _process_media_status ( self , data ) : <EOL> """<STR_LIT>""" <EOL> self . status . update ( data ) <EOL> self . logger . debug ( "<STR_LIT>" , data ) <EOL> self . _fire_status_changed ( ) <EOL> def _fire_status_changed ( self ) : <EOL> """<STR_LIT>""" <EOL> for listener in self . _status_listeners : <EOL> try : <EOL> listener . new_media_status ( self . status ) <EOL> except Exception : <EOL> pass <EOL> def play_media ( self , url , content_type , title = None , thumb = None , <EOL> current_time = <NUM_LIT:0> , autoplay = True , <EOL> stream_type = STREAM_TYPE_BUFFERED , <EOL> metadata = None ) : <EOL> """<STR_LIT>""" <EOL> self . _socket_client . receiver_controller . launch_app ( APP_MEDIA_RECEIVER ) <EOL> msg = { <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT>' : url , <EOL> '<STR_LIT>' : stream_type , <EOL> '<STR_LIT>' : content_type , <EOL> '<STR_LIT>' : metadata or { } <EOL> } , <EOL> MESSAGE_TYPE : TYPE_LOAD , <EOL> '<STR_LIT>' : current_time , <EOL> '<STR_LIT>' : autoplay , <EOL> '<STR_LIT>' : { } <EOL> } <EOL> if title : <EOL> msg [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT:title>' ] = title <EOL> if thumb : <EOL> msg [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] = thumb <EOL> if '<STR_LIT>' not in msg [ '<STR_LIT>' ] [ '<STR_LIT>' ] : <EOL> msg [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] = [ ] <EOL> msg [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] . append ( { '<STR_LIT:url>' : thumb } ) <EOL> self . send_message ( msg , inc_session_id = True ) <EOL> def tear_down ( self ) : <EOL> """<STR_LIT>""" <EOL> super ( MediaController , self ) . tear_down ( ) <EOL> self . _status_listeners [ : ] = [ ] </s>
