Пример #1
0
class MenuShow(Show):
    def __init__(self, show_id, show_params, root, canvas, showlist, pp_dir,
                 pp_home, pp_profile, command_callback):
        """
            show_id - index of the top level show caling this (for debug only)
            show_params - dictionary section for the menu
            canvas - the canvas that the menu is to be written on
            showlist  - the showlist
            pp_dir - Pi Presents directory
            pp_home - Pi presents data_home directory
            pp_profile - Pi presents profile directory
        """

        # init the common bits
        Show.base__init__(self, show_id, show_params, root, canvas, showlist,
                          pp_dir, pp_home, pp_profile, command_callback)

        # instatiatate the screen driver - used only to access enable and hide click areas
        self.sr = ScreenDriver()

        self.controlsmanager = ControlsManager()

        # init variables
        self.show_timeout_timer = None
        self.track_timeout_timer = None
        self.next_track_signal = False
        self.next_track = None
        self.menu_index = 0
        self.menu_showing = True
        self.req_next = ''
        self.last_menu_index = 0
        self.return_to_zero = False

    def play(self, end_callback, show_ready_callback, parent_kickback_signal,
             level, controls_list):
        """ displays the menu 
              end_callback - function to be called when the menu exits
              show_ready_callback - callback when menu is ready to display (not used)
              level is 0 when the show is top level (run from [start] or from show control)
              parent_kickback_signal  - not used other than it being passed to a show
        """
        # need to instantiate the medialist here as not using gapshow
        self.medialist = MediaList('ordered')

        Show.base_play(self, end_callback, show_ready_callback,
                       parent_kickback_signal, level, controls_list)

        self.mon.trace(self, self.show_params['show-ref'])

        #parse the show and track timeouts
        reason, message, self.show_timeout = Show.calculate_duration(
            self, self.show_params['show-timeout'])
        if reason == 'error':
            self.mon.err(
                self, 'Show Timeout has bad time: ' +
                self.show_params['show-timeout'])
            self.end(
                'error',
                'show timeout, bad time: ' + self.show_params['show-timeout'])

        reason, message, self.track_timeout = Show.calculate_duration(
            self, self.show_params['track-timeout'])
        if reason == 'error':
            self.mon.err(
                self, 'Track Timeout has bad time: ' +
                self.show_params['track-timeout'])
            self.end(
                'error', 'track timeout, bad time: ' +
                self.show_params['track-timeout'])

        # and delete eggtimer
        if self.previous_shower is not None:
            self.previous_shower.delete_eggtimer()

        # and display the menu
        self.do_menu_track()

# ********************
# respond to inputs.
# ********************

# exit received from another concurrent show

    def exit(self):
        self.stop_timers()
        Show.base_exit(self)

    #  show timeout happened
    def show_timeout_stop(self):
        self.stop_timers()
        Show.base_show_timeout_stop(self)

    # terminate Pi Presents
    def terminate(self):
        self.stop_timers()
        Show.base_terminate(self)

    def handle_input_event(self, symbol):
        Show.base_handle_input_event(self, symbol)

    def handle_input_event_this_show(self, symbol):

        self.handle_show_control_event(symbol, self.show_control_controls)

        # menushow has only internal operation
        operation = self.base_lookup_control(symbol, self.controls_list)
        self.do_operation(operation)

    def do_operation(self, operation):
        # service the standard inputs for this show

        self.mon.trace(self, operation)
        if operation == 'exit':
            self.exit()

        elif operation == 'stop':
            self.stop_timers()
            if self.current_player is not None:
                if self.menu_showing is True and self.level != 0:
                    # if quiescent then set signal to stop the show when track has stopped
                    self.user_stop_signal = True
                self.current_player.input_pressed('stop')

        elif operation in ('up', 'down'):
            # stop show timeout
            if self.show_timeout_timer is not None:
                self.canvas.after_cancel(self.show_timeout_timer)
                # and start it again
                if self.show_timeout != 0:
                    self.show_timeout_timer = self.canvas.after(
                        self.show_timeout * 1000, self.show_timeout_stop)
            if operation == 'up':
                self.previous()
            else:
                next(self)

        elif operation == 'play':
            self.next_track_signal = True
            st = self.medialist.select_anon_by_index(self.menu_index)
            self.next_track = self.medialist.selected_track()
            self.current_player.stop()

            # cancel show timeout
            if self.show_timeout_timer is not None:
                self.canvas.after_cancel(self.show_timeout_timer)
                self.show_timeout_timer = None

            # stop current track (the menuplayer) if running or just start the next track
            if self.current_player is not None:
                self.current_player.input_pressed('stop')
            else:
                self.what_next_after_showing()

        elif operation in ('no-command', 'null'):
            return

        elif operation in ('pause', 'pause-on', 'pause-off', 'mute', 'unmute',
                           'go'):
            if self.current_player is not None:
                self.current_player.input_pressed(operation)

        elif operation[0:4] == 'omx-' or operation[
                0:6] == 'mplay-' or operation[0:5] == 'uzbl-':
            if self.current_player is not None:
                self.current_player.input_pressed(operation)

    def __next__(self):
        # remove highlight
        if self.current_player.__class__.__name__ == 'MenuPlayer':
            self.current_player.highlight_menu_entry(self.menu_index, False)
            self.medialist.next('ordered')
            if self.menu_index == self.menu_length - 1:
                self.menu_index = 0
            else:
                self.menu_index += 1
            # and highlight the new entry
            self.current_player.highlight_menu_entry(self.menu_index, True)

    def previous(self):
        # remove highlight
        if self.current_player.__class__.__name__ == 'MenuPlayer':
            self.current_player.highlight_menu_entry(self.menu_index, False)
            if self.menu_index == 0:
                self.menu_index = self.menu_length - 1
            else:
                self.menu_index -= 1
            self.medialist.previous('ordered')
            # and highlight the new entry
            self.current_player.highlight_menu_entry(self.menu_index, True)

# *********************
# Sequencing
# *********************

    def track_timeout_callback(self):
        self.do_operation('stop')

    def do_menu_track(self):
        self.menu_showing = True
        self.mon.trace(self, '')
        # start show timeout alarm if required
        if self.show_timeout != 0:
            self.show_timeout_timer = self.canvas.after(
                self.show_timeout * 1000, self.show_timeout_stop)

        index = self.medialist.index_of_track(
            self.show_params['menu-track-ref'])
        if index == -1:
            self.mon.err(
                self, "'menu-track' not in medialist: " +
                self.show_params['menu-track-ref'])
            self.end(
                'error', "menu-track not in medialist: " +
                self.show_params['menu-track-ref'])
            return

        #make the medialist available to the menuplayer for cursor scrolling
        self.show_params['medialist_obj'] = self.medialist

        # load the menu track
        self.start_load_show_loop(self.medialist.track(index))

# *********************
# Playing show or track loop
# *********************

    def start_load_show_loop(self, selected_track):
        # shuffle players
        Show.base_shuffle(self)
        self.mon.trace(self, '')
        self.display_eggtimer()

        # get control bindings for this show
        # needs to be done for each track as track can override the show controls
        if self.show_params['disable-controls'] == 'yes':
            self.controls_list = []
        else:
            reason, message, self.controls_list = self.controlsmanager.get_controls(
                self.show_params['controls'])
            if reason == 'error':
                self.mon.err(self, message)
                self.end('error', "error in controls: " + message)
                return

        # load the track or show
        Show.base_load_track_or_show(self, selected_track,
                                     self.what_next_after_load,
                                     self.end_shower, False)

# track has loaded (menu or otherwise) so show it.

    def what_next_after_load(self, status, message):

        if self.current_player.play_state == 'load-failed':
            self.req_next = 'error'
            self.what_next_after_showing()

        else:
            # get the calculated length of the menu for the loaded menu track
            if self.current_player.__class__.__name__ == 'MenuPlayer':
                if self.medialist.anon_length() == 0:
                    self.req_next = 'error'
                    self.what_next_after_showing()
                    return

                #highlight either first or returning entry and select appropiate medialist entry
                if self.return_to_zero is True:
                    # init the index used to hiighlight the selected menu entry by menuplayer
                    self.menu_index = 0
                    # print 'initial index',self.menu_index
                else:
                    self.menu_index = self.last_menu_index
                    # print ' return to last ',self.menu_index

                self.menu_length = self.current_player.menu_length
                self.current_player.highlight_menu_entry(self.menu_index, True)
            self.mon.trace(
                self, ' - load complete with status: ' + status +
                '  message: ' + message)

            if self.show_timeout_signal is True or self.terminate_signal is True or self.exit_signal is True or self.user_stop_signal is True:
                self.what_next_after_showing()
            else:
                self.mon.trace(self, '')
                self.current_player.show(self.track_ready_callback,
                                         self.finished_showing,
                                         self.closed_after_showing)

    def finished_showing(self, reason, message):
        # showing has finished with 'pause at end', showing the next track will close it after next has started showing
        self.mon.trace(self, '')
        self.mon.log(
            self, "pause at end of showing track with reason: " + reason +
            ' and message: ' + message)
        self.sr.hide_click_areas(self.controls_list, self.canvas)
        if self.current_player.play_state == 'show-failed':
            self.req_next = 'error'
        else:
            self.req_next = 'finished-player'
        self.what_next_after_showing()

    def closed_after_showing(self, reason, message):
        # showing has finished with closing of player but track instance is alive for hiding the x_content
        self.mon.trace(self, '')
        self.mon.log(
            self, "Closed after showing track with reason: " + reason +
            ' and message: ' + message)
        self.sr.hide_click_areas(self.controls_list, self.canvas)
        if self.current_player.play_state == 'show-failed':
            self.req_next = 'error'
        else:
            self.req_next = 'closed-player'
        self.what_next_after_showing()

    # subshow or child show has ended
    def end_shower(self, show_id, reason, message):
        self.mon.log(
            self, self.show_params['show-ref'] + ' ' + str(self.show_id) +
            ': Returned from shower with ' + reason + ' ' + message)
        self.sr.hide_click_areas(self.controls_list, self.canvas)
        self.req_next = reason
        Show.base_end_shower(self)
        self.what_next_after_showing()

    # at the end of a track check for terminations else re-display the menu
    def what_next_after_showing(self):
        self.mon.trace(self, '')
        # cancel track timeout timer
        if self.track_timeout_timer is not None:
            self.canvas.after_cancel(self.track_timeout_timer)
            self.track_timeout_timer = None

        # need to terminate?
        if self.terminate_signal is True:
            self.terminate_signal = False
            # set what to do when closed or unloaded
            self.ending_reason = 'killed'
            Show.base_close_or_unload(self)

        elif self.req_next == 'error':
            self.req_next = ''
            # set what to do after closed or unloaded
            self.ending_reason = 'error'
            Show.base_close_or_unload(self)

        # show timeout
        elif self.show_timeout_signal is True:
            self.show_timeout_signal = False
            # set what to do when closed or unloaded
            self.ending_reason = 'show-timeout'
            Show.base_close_or_unload(self)

        # used by exit for stopping show from other shows.
        elif self.exit_signal is True:
            self.exit_signal = False
            self.ending_reason = 'exit'
            Show.base_close_or_unload(self)

        # user wants to stop
        elif self.user_stop_signal is True:
            self.user_stop_signal = False
            self.ending_reason = 'user-stop'
            Show.base_close_or_unload(self)

        elif self.next_track_signal is True:
            self.next_track_signal = False
            self.menu_showing = False
            # start timeout for the track if required
            if self.track_timeout != 0:
                self.track_timeout_timer = self.canvas.after(
                    self.track_timeout * 1000, self.track_timeout_callback)
            self.last_menu_index = self.menu_index
            Show.write_stats(self, 'play', self.show_params, self.next_track)
            self.start_load_show_loop(self.next_track)

        else:
            # no stopping the show required so re-display the menu
            self.do_menu_track()

# *********************
# Interface with other shows/players to reduce black gaps
# *********************

# called just before a track is shown to remove the  previous track from the screen
# and if necessary close it

    def track_ready_callback(self, enable_show_background):
        self.delete_eggtimer()

        if self.show_params['disable-controls'] != 'yes':
            #merge controls from the track
            controls_text = self.current_player.get_links()
            reason, message, track_controls = self.controlsmanager.parse_controls(
                controls_text)
            if reason == 'error':
                self.mon.err(
                    self, message + " in track: " +
                    self.current_player.track_params['track-ref'])
                self.req_next = 'error'
                self.what_next_after_showing()
            self.controlsmanager.merge_controls(self.controls_list,
                                                track_controls)

        self.sr.enable_click_areas(self.controls_list, self.canvas)

        Show.base_track_ready_callback(self, enable_show_background)

    # callback from begining of a subshow, provide previous shower player to called show
    def subshow_ready_callback(self):
        return Show.base_subshow_ready_callback(self)

# *********************
# Ending the show
# *********************

    def end(self, reason, message):
        self.stop_timers()
        Show.base_end(self, reason, message)

    def stop_timers(self):
        if self.track_timeout_timer is not None:
            self.canvas.after_cancel(self.track_timeout_timer)
            self.track_timeout_timer = None
        if self.show_timeout_timer is not None:
            self.canvas.after_cancel(self.show_timeout_timer)
            self.show_timeout_timer = None
Пример #2
0
class MenuShow(Show):

    def __init__(self,
                 show_id,
                 show_params,
                 root,
                 canvas,
                 showlist,
                 pp_dir,
                 pp_home,
                 pp_profile,
                 command_callback):
        
        """
            show_id - index of the top level show caling this (for debug only)
            show_params - dictionary section for the menu
            canvas - the canvas that the menu is to be written on
            showlist  - the showlist
            pp_dir - Pi Presents directory
            pp_home - Pi presents data_home directory
            pp_profile - Pi presents profile directory
        """

        # init the common bits
        Show.base__init__(self,
                          show_id,
                          show_params,
                          root,
                          canvas,
                          showlist,
                          pp_dir,
                          pp_home,
                          pp_profile,
                          command_callback)
        

        # instatiatate the screen driver - used only to access enable and hide click areas
        self.sr=ScreenDriver()

        self.controlsmanager=ControlsManager()

        # init variables
        self.show_timeout_timer=None
        self.track_timeout_timer=None
        self.next_track_signal=False
        self.next_track=None
        self.menu_index=0
        self.menu_showing=True
        self.req_next=''
        self.last_menu_index=0
        self.return_to_zero=False



    def play(self,end_callback,show_ready_callback,parent_kickback_signal,level,controls_list):
        """ displays the menu 
              end_callback - function to be called when the menu exits
              show_ready_callback - callback when menu is ready to display (not used)
              level is 0 when the show is top level (run from [start] or from show control)
              parent_kickback_signal  - not used other than it being passed to a show
        """
        # need to instantiate the medialist here as not using gapshow
        self.medialist=MediaList('ordered')

        Show.base_play(self,end_callback,show_ready_callback, parent_kickback_signal,level,controls_list)
        
        self.mon.trace(self,self.show_params['show-ref'])

        #parse the show and track timeouts
        reason,message,self.show_timeout=Show.calculate_duration(self,self.show_params['show-timeout'])
        if reason =='error':
            self.mon.err(self,'Show Timeout has bad time: '+self.show_params['show-timeout'])
            self.end('error','show timeout, bad time: ' + self.show_params['show-timeout'])

        reason,message,self.track_timeout=Show.calculate_duration(self,self.show_params['track-timeout'])
        if reason=='error':
            self.mon.err(self,'Track Timeout has bad time: '+self.show_params['track-timeout'])
            self.end('error','track timeout, bad time: ' + self.show_params['track-timeout'])
            
        # and delete eggtimer
        if self.previous_shower is not None:
            self.previous_shower.delete_eggtimer()

        # and display the menu 
        self.do_menu_track()


# ********************
# respond to inputs.
# ********************

    # exit received from another concurrent show
    def exit(self):
        self.stop_timers()
        Show.base_exit(self)

    #  show timeout happened
    def show_timeout_stop(self):
        self.stop_timers()
        Show.base_show_timeout_stop(self)

    # terminate Pi Presents
    def terminate(self):
        self.stop_timers()
        Show.base_terminate(self)            


    def  handle_input_event(self,symbol):
        Show.base_handle_input_event(self,symbol)


    def handle_input_event_this_show(self,symbol):
        # menushow has only internal operation
        operation=self.base_lookup_control(symbol,self.controls_list)
        self.do_operation(operation)


    def do_operation(self,operation):
        # service the standard inputs for this show

        self.mon.trace(self,operation)
        if operation =='exit':
            self.exit()
            
        elif operation == 'stop':
            self.stop_timers()
            if self.current_player is not None:
                if self.menu_showing is True  and self.level != 0:
                    # if quiescent then set signal to stop the show when track has stopped
                    self.user_stop_signal=True
                self.current_player.input_pressed('stop')
      
        elif operation in ('up','down'):
            # stop show timeout
            if self.show_timeout_timer is not None:
                self.canvas.after_cancel(self.show_timeout_timer)
                # and start it again
                if self.show_timeout != 0:
                    self.show_timeout_timer=self.canvas.after(self.show_timeout*1000,self.show_timeout_stop)
            if operation=='up':
                self.previous()
            else:
                self.next()
                
        elif operation =='play':
            self.next_track_signal=True
            st=self.medialist.select_anon_by_index(self.menu_index)
            self.next_track=self.medialist.selected_track()
            self.current_player.stop()


            # cancel show timeout
            if self.show_timeout_timer is not None:
                self.canvas.after_cancel(self.show_timeout_timer)
                self.show_timeout_timer=None

            # stop current track (the menuplayer) if running or just start the next track
            if self.current_player is not None:
                self.current_player.input_pressed('stop')
            else:
                self.what_next_after_showing()
                
        elif operation  in ('no-command','null'):
            return

        elif operation in ('pause','pause-on','pause-off','mute','unmute','go'):
            if self.current_player is not None:
                self.current_player.input_pressed(operation)
                
        elif operation[0:4]=='omx-' or operation[0:6]=='mplay-'or operation[0:5]=='uzbl-':
            if self.current_player is not None:
                self.current_player.input_pressed(operation)

        
    def next(self):
        # remove highlight
        if self.current_player.__class__.__name__ == 'MenuPlayer':
            self.current_player.highlight_menu_entry(self.menu_index,False)
            self.medialist.next('ordered')
            if self.menu_index==self.menu_length-1:
                self.menu_index=0
            else:
                self.menu_index+=1
            # and highlight the new entry
            self.current_player.highlight_menu_entry(self.menu_index,True)     


    def previous(self):
        # remove highlight
        if self.current_player.__class__.__name__ == 'MenuPlayer':
            self.current_player.highlight_menu_entry(self.menu_index,False)
            if self.menu_index==0:
                self.menu_index=self.menu_length-1
            else:
                self.menu_index-=1
            self.medialist.previous('ordered')
            # and highlight the new entry
            self.current_player.highlight_menu_entry(self.menu_index,True)
        

# *********************
# Sequencing
# *********************

    def track_timeout_callback(self):
        self.do_operation('stop')

    def do_menu_track(self):
        self.menu_showing=True
        self.mon.trace(self,'')
        # start show timeout alarm if required
        if self.show_timeout != 0:
            self.show_timeout_timer=self.canvas.after(self.show_timeout *1000,self.show_timeout_stop)

        index = self.medialist.index_of_track(self.show_params['menu-track-ref'])
        if index == -1:
                self.mon.err(self,"'menu-track' not in medialist: " + self.show_params['menu-track-ref'])
                self.end('error',"menu-track not in medialist: " + self.show_params['menu-track-ref'])
                return
        
        #make the medialist available to the menuplayer for cursor scrolling
        self.show_params['medialist_obj']=self.medialist
        
        # load the menu track 
        self.start_load_show_loop(self.medialist.track(index))


# *********************
# Playing show or track loop
# *********************

    def start_load_show_loop(self,selected_track):
        # shuffle players
        Show.base_shuffle(self)
        self.mon.trace(self,'')
        self.display_eggtimer()

        # get control bindings for this show
        # needs to be done for each track as track can override the show controls
        if self.show_params['disable-controls'] == 'yes':
            self.controls_list=[]
        else:
            reason,message,self.controls_list= self.controlsmanager.get_controls(self.show_params['controls'])
            if reason=='error':
                self.mon.err(self,message)
                self.end('error',"error in controls: " + message)
                return

        # load the track or show
        Show.base_load_track_or_show(self,selected_track,self.what_next_after_load,self.end_shower,False)

 
  # track has loaded (menu or otherwise) so show it.
    def what_next_after_load(self,status,message):

        if self.current_player.play_state=='load-failed':
            self.req_next='error'
            self.what_next_after_showing()

        else:
            # get the calculated length of the menu for the loaded menu track
            if self.current_player.__class__.__name__ == 'MenuPlayer':
                if self.medialist.anon_length()==0:
                    self.req_next='error'
                    self.what_next_after_showing()
                    return

                #highlight either first or returning entry and select appropiate medialist entry
                if self.return_to_zero is True:
                    # init the index used to hiighlight the selected menu entry by menuplayer
                    self.menu_index=0
                    # print 'initial index',self.menu_index
                else:
                    self.menu_index=self.last_menu_index
                    # print ' return to last ',self.menu_index

                
                self.menu_length=self.current_player.menu_length
                self.current_player.highlight_menu_entry(self.menu_index,True)
            self.mon.trace(self,' - load complete with status: ' + status + '  message: ' + message)


            if self.show_timeout_signal is True or self.terminate_signal  is True or self.exit_signal  is True or self.user_stop_signal  is True:
                self.what_next_after_showing()
            else:
                self.mon.trace(self,'')
                self.current_player.show(self.track_ready_callback,self.finished_showing,self.closed_after_showing)


    def finished_showing(self,reason,message):
        # showing has finished with 'pause at end', showing the next track will close it after next has started showing
        self.mon.trace(self,'')
        self.mon.log(self,"pause at end of showing track with reason: "+reason+ ' and message: '+ message)
        self.sr.hide_click_areas(self.controls_list)
        if self.current_player.play_state == 'show-failed':
            self.req_next = 'error'
        else:
            self.req_next='finished-player'
        self.what_next_after_showing()

    def closed_after_showing(self,reason,message):
        # showing has finished with closing of player but track instance is alive for hiding the x_content
        self.mon.trace(self,'')
        self.mon.log(self,"Closed after showing track with reason: "+reason+ ' and message: '+ message)
        self.sr.hide_click_areas(self.controls_list)
        if self.current_player.play_state == 'show-failed':
            self.req_next = 'error'
        else:
            self.req_next='closed-player'
        self.what_next_after_showing()

    # subshow or child show has ended
    def end_shower(self,show_id,reason,message):
        self.mon.log(self,self.show_params['show-ref']+ ' '+ str(self.show_id)+ ': Returned from shower with ' + reason +' ' + message)
        self.sr.hide_click_areas(self.controls_list)        
        self.req_next=reason
        Show.base_end_shower(self)
        self.what_next_after_showing()
 

     # at the end of a track check for terminations else re-display the menu      
    def what_next_after_showing(self):
        self.mon.trace(self,'')
        # cancel track timeout timer
        if self.track_timeout_timer is not None:
            self.canvas.after_cancel(self.track_timeout_timer)
            self.track_timeout_timer=None
            
        # need to terminate?
        if self.terminate_signal is True:
            self.terminate_signal=False
            # set what to do when closed or unloaded
            self.ending_reason='killed'
            Show.base_close_or_unload(self)

        elif self.req_next== 'error':
            self.req_next=''
            # set what to do after closed or unloaded
            self.ending_reason='error'
            Show.base_close_or_unload(self)

        # show timeout
        elif self.show_timeout_signal is True:
            self.show_timeout_signal=False
            # set what to do when closed or unloaded
            self.ending_reason='show-timeout'
            Show.base_close_or_unload(self)

        # used by exit for stopping show from other shows. 
        elif self.exit_signal is True:
            self.exit_signal=False
            self.ending_reason='exit'
            Show.base_close_or_unload(self)

        # user wants to stop
        elif self.user_stop_signal is True:
            self.user_stop_signal=False
            self.ending_reason='user-stop'
            Show.base_close_or_unload(self)

        elif self.next_track_signal is True:
            self.next_track_signal=False
            self.menu_showing=False
            # start timeout for the track if required           
            if self.track_timeout != 0:
                self.track_timeout_timer=self.canvas.after(self.track_timeout*1000,self.track_timeout_callback)
            self.last_menu_index=self.menu_index
            Show.write_stats(self,'play',self.show_params,self.next_track)
            self.start_load_show_loop(self.next_track)
            
        else:
            # no stopping the show required so re-display the menu
            self.do_menu_track()


# *********************
# Interface with other shows/players to reduce black gaps
# *********************

    # called just before a track is shown to remove the  previous track from the screen
    # and if necessary close it
    def track_ready_callback(self,enable_show_background):
        self.delete_eggtimer()

        if self.show_params['disable-controls'] != 'yes':        
            #merge controls from the track
            controls_text=self.current_player.get_links()
            reason,message,track_controls=self.controlsmanager.parse_controls(controls_text)
            if reason == 'error':
                self.mon.err(self,message + " in track: "+ self.current_player.track_params['track-ref'])
                self.req_next='error'
                self.what_next_after_showing()
            self.controlsmanager.merge_controls(self.controls_list,track_controls)

        self.sr.enable_click_areas(self.controls_list)
        
        Show.base_track_ready_callback(self,enable_show_background)

    # callback from begining of a subshow, provide previous shower player to called show        
    def subshow_ready_callback(self):
        return Show.base_subshow_ready_callback(self)



# *********************
# Ending the show
# *********************

    def end(self,reason,message):
        self.stop_timers()
        Show.base_end(self,reason,message)


    def stop_timers(self):
        if self.track_timeout_timer is not None:
            self.canvas.after_cancel(self.track_timeout_timer)
            self.track_timeout_timer=None
        if self.show_timeout_timer is not None:
            self.canvas.after_cancel(self.show_timeout_timer)
            self.show_timeout_timer=None