def __init__(self, iface, serie_model, injector): self.app = iface self.current_process = None self.injector = injector # injected classes self.player_handler = injector.get_instance(ExternalPlayerHandler) self.video_finder_controller = injector.get_instance(VideoFinderController) logging.debug ("creating event manager") self.play_buttons = ["Play", "SlaveMplayerPlay", "DlSub", "OpenRep"] self.serie_model = serie_model logging.debug ("Setting up file monitoring ... ") nomfic = serie_model.get_base_path() fichier = Gio.File.new_for_path(nomfic) if(fichier): self.monitor = fichier.monitor_directory(Gio.FileMonitorFlags.NONE, None) self.monitor.connect("changed", self.update_serie_list) self.player_status = PlayerStatus() ## subtitle view init cellpb = Gtk.CellRendererText() cellpbtext = Gtk.CellRendererText() time = Gtk.TreeViewColumn("Début", cellpb) time.set_cell_data_func(cellpb, ui.subtitles.subtitle_begin_time_getter) column = Gtk.TreeViewColumn("Sous-Titre", cellpbtext, text =1) column.set_cell_data_func(cellpbtext, ui.subtitles.subtitle_line_text_getter) sub_treeview = self.app.getitem("SubtitlesTreeView") sub_treeview.append_column(time) sub_treeview.append_column(column) sub_treeview.set_enable_search(True) sub_treeview.set_search_column(1) # num_trad_column-1) sub_treeview.set_search_equal_func(\ ui.subtitles.subtitle_comparison_function, "") # init of video finder window ui.videotorrent_list_model\ .init_torrentlist_viewer(\ self.app.getitem("TorrentList")) ## MPlayer subwindow # self.MPlayer = mplayer_slave.player(self.\ #iface.getitem("VideoZone").window.xid) # self.MPlayer = mplayer_slave.player(None) # self.MPlayer = mplayer_slave.player(None) # self.app.getitem("VideoZone").window.xid) # logging.info ("XID :", self.app.getitem("VideoZone").window.xid) # self.payer_status = None # Gio File watching handles self.handle_file = None self.handle_end = None self.subtitle_downloader = injector.get_instance(Subdownloader) self.monitor_serie = None # making an attribute to prevent gc self.manager = None self.update_serie_view()
class PlayEventManager(object): """ Class regrouping l callbacks and data updating functions """ def __init__(self, iface, serie_model, injector): self.app = iface self.current_process = None self.injector = injector # injected classes self.player_handler = injector.get_instance(ExternalPlayerHandler) self.video_finder_controller = injector.get_instance(VideoFinderController) logging.debug ("creating event manager") self.play_buttons = ["Play", "SlaveMplayerPlay", "DlSub", "OpenRep"] self.serie_model = serie_model logging.debug ("Setting up file monitoring ... ") nomfic = serie_model.get_base_path() fichier = Gio.File.new_for_path(nomfic) if(fichier): self.monitor = fichier.monitor_directory(Gio.FileMonitorFlags.NONE, None) self.monitor.connect("changed", self.update_serie_list) self.player_status = PlayerStatus() ## subtitle view init cellpb = Gtk.CellRendererText() cellpbtext = Gtk.CellRendererText() time = Gtk.TreeViewColumn("Début", cellpb) time.set_cell_data_func(cellpb, ui.subtitles.subtitle_begin_time_getter) column = Gtk.TreeViewColumn("Sous-Titre", cellpbtext, text =1) column.set_cell_data_func(cellpbtext, ui.subtitles.subtitle_line_text_getter) sub_treeview = self.app.getitem("SubtitlesTreeView") sub_treeview.append_column(time) sub_treeview.append_column(column) sub_treeview.set_enable_search(True) sub_treeview.set_search_column(1) # num_trad_column-1) sub_treeview.set_search_equal_func(\ ui.subtitles.subtitle_comparison_function, "") # init of video finder window ui.videotorrent_list_model\ .init_torrentlist_viewer(\ self.app.getitem("TorrentList")) ## MPlayer subwindow # self.MPlayer = mplayer_slave.player(self.\ #iface.getitem("VideoZone").window.xid) # self.MPlayer = mplayer_slave.player(None) # self.MPlayer = mplayer_slave.player(None) # self.app.getitem("VideoZone").window.xid) # logging.info ("XID :", self.app.getitem("VideoZone").window.xid) # self.payer_status = None # Gio File watching handles self.handle_file = None self.handle_end = None self.subtitle_downloader = injector.get_instance(Subdownloader) self.monitor_serie = None # making an attribute to prevent gc self.manager = None self.update_serie_view() def update_serie_list(self, monitor, fichier, data, event): #pylint: disable=W0613 """ Callbacks when a new file is added in the Serie directory, Action : updates the Serie Combo """ logging.info("Recherche d'une nouvelle série") model = self.app.getitem("SerieListCombo").get_model() serie_list = self.manager.get_serie_list() new_items = [x for x in serie_list if not self.serie_model.series.has_key(x) ] for new_serie in new_items: self.serie_model.add_serie(new_serie) model.append([new_serie]) def update_subs_and_file(self, monitor, fichier, data, event):\ #pylint: disable=W0613 """ Callbacks when a new file is added on the Season directory Action : calls update_serie """ logging.info("Recherche d'un nouveau sub / vidéo ?") if ( event == Gio.FileMonitorEvent.CREATED ): self.update_episode_view() def open_filemanager(self, widg):#pylint: disable=W0613 """ Opens a Nautilus Window on current season directory""" command_launch = CommandExecuter() command_gen = CommandLineGenerator("xdg-open") rep = self.serie_model.get_current_serie().get_path_to_current_season() command_gen.add_option_single(rep) command_launch.get_output(command_gen.get_command()) def play(self, widg):#pylint: disable=W0613 """ Callback when a play is requested ** Unused currently **, probably obsolete Action : Launches 'play' script with current episode parameters""" logging.info("playing ... " + self.serie_model.get_current_serie().name) if self.current_process == None : serie = self.serie_model.get_current_serie() command = CommandLineGenerator("serie_next") chemin_serie = self.serie_model.get_current_serie().get_path_to_serie() epi = serie.season.episode command.add_option_param("-s", unicode(serie.season.number)) command.add_option_param("-e", unicode(epi.number)) command.add_option_param("-G", unicode(serie.get_skip_time())) fps = serie.get_fps() if fps: command.add_option_param("-f", unicode(fps)) command.add_option_param("-d", unicode(serie.get_decay_time())) subfile = get_combo_value(self.app.getitem("CandidateSubsCombo")) if subfile: command.add_option_param("-t", subfile) vidfile = self.app.getitem("NomficLabel").get_text() if vidfile: command.add_option_param("-v", vidfile) #TODO: replace this legacy code os.environ["SEASON"] = self.serie_model.current_serie.name self.player_handler.execute_play_command(self, command.get_command(), cwd = chemin_serie) def end_of_play(self, widg = None, condition = None):#pylint: disable=W0613 """ Callbacks called when the MPlayer process stops Action : reactivates buttons, launches UI updates for next episode, update models """ logging.info("end of play !") for nom in self.play_buttons : self.app.getitem(nom).set_sensitive(True) self.current_process = None if not self.app.getitem("SetupModeCheck").get_active(): self.serie_model.current_serie.on_seen_episode() self.update_serie_view() return False def play_windowed(self, widg):#pylint: disable=W0613 """ Callback when button is clicked Actions * Launches MPlayer, in a window, * sets UI in playing mode * installs end of play callbacks """ #if self.current_process == None : # self.execute_play_command(["series","-S"]) logging.info("playing in a slave MPlayer !!") #if self.MPlayer == None: # self.MPlayer = mplayer_slave.player(\ # self.app.getitem("VideoZone").window.xid) # self.MPlayer = mplayer_slave.player() #self.app.getitem("VideoZone").window.xid) # pass # else: serie = self.serie_model.current_serie vid_list = serie.season.episode.get_video_list() filename = None if len(vid_list) > 0: filename = serie.get_absolute_filename(vid_list[0]) path = serie.get_path_to_current_season() sublist = serie.season.episode.get_subtitle_list() if len(sublist) > 0 : subfile = sublist[0] else: sublist = None if filename != None : self.player_status.play(filename) (width, height)= self.player_status.get_video_resolution() logging.debug("size : {0}x{1}".format(width, height)) drawing_area = self.app.getitem("VideoZone") drawing_area.set_size_request(width, height) # gdkwindow = drawing_area.window logging.debug("trying to go fullscreen ...") # new_window = Gtk.Window(Gtk.WINDOW_TOPLEVEL) #new_window.fullscreen() #drawing_area.set_parent_window(new_window.get_parent_window()) # self.player_status = Player_status(self.MPlayer) # self.player_status.play(filename) status = self.player_status status.set_playing() status.set_subtitles(subfile) #pylint: disable = E1101 status.connect("play_ended", self.end_of_play) self.update_serie_view() def search_subtitles(self, btn):#pylint: disable=W0613 """TODO : Upgrade to twisted async method for findind subtitles Subtitles finders simply write results in current season directory """ logging.debug("searching ... in a thread") chemin_serie = self.serie_model.get_current_serie()\ .get_path_to_current_season() arguments = [self.serie_model, self.subtitle_downloader] methode = thr_sub_dl subdl_worker = threading.Thread(\ name = "thread_sub"+chemin_serie, args = arguments, target = methode) subdl_worker.start() logging.debug("searching done ! ...") def subtitle_seek(self, treeview, path, column):#pylint: disable=W0613 """ Callback when users wants to go to a subtitles instant in the video Action : sends a seek command to MPLayer to the date of current selected subtitle in subtitle view """ (model, itera)= treeview.get_selection().get_selected() time = model.get_value(itera, 0).start self.player_status.handle_seek(time) def subtitle_sync(self, button):#pylint: disable=W0613 """ Callback when user wants to decay subtitles to a current time Action : sets the decay_subtitle value to MPLayer corresponding roughly to the difference beetween : current time in the video, and selected subtitle time """ # getting datas treeview = self.app.getitem("SubtitlesTreeView") (model, itera)= treeview.get_selection().get_selected() time = model.get_value(itera, 0).start.ordinal / 1000 in_video_time = self.player_status.get_current_time() sub_delay = self.player_status.get_subtitles_delay() # calculating delay = time - in_video_time logging.info("time = {0} ; \ in video time = {1} ;\ sub_delay calculated = {}" .format(time, in_video_time, sub_delay)) # sending command self.player_status.set_subtitles_delay(delay) def playing(self): """ Action function : sets the interface in playing mode """ for nom in self.play_buttons: self.app.getitem(nom).set_sensitive(False) return ( self.current_process == None ) def update_serie_view(self): """ Callback when [lots of calls ] Action : * Reads the current Store configuration to Serie Manager (current serie, ...) * and sets up interface accordingly """ # just to update season view at the moment, # no way to change serie other than manually # TODO: watch if that changes self.update_season_view() def update_season_view(self): """ Callback when season number in serie changed. Action : * update the serie & episode view """ serie = (self.serie_model.current_serie) newsaison = int(serie.season_num) spin = self.app.getitem("numSaisonSpin") spin.set_value(newsaison) self.update_episode_view() @property def serie(self): """ getter for current selected serie""" return self.serie_model.current_serie def update_episode_view(self): """ Callback when a new episode must be shown Action : * update episode number * loads sutitles & video name candidates """ serie = self.serie_model.current_serie newep = serie.season.episode.number self.app.getitem("numEpSpin").set_value(newep) self.app.getitem("skipTimeSpin").set_value(serie.get_skip_time()) self.app.getitem("decayTimeSpin").set_value(serie.get_decay_time()) vid_list = serie.get_video_list() logging.info("Videos !!! nb:{}".format(len(vid_list))) logging.info(vid_list) if len (vid_list) > 0 : self.app.getitem("NomficLabel").set_text(vid_list[0]) else: episode = Episode(serie, serie.season, newep) self.add_video_finder(episode) self.app.getitem("NomficLabel").set_text("") self.update_subs() def add_video_finder(self, episode): """ Ubuesque code cascade & design trigerring """ controller = self.video_finder_controller controller.add_video_finder(self.app, episode) def selected_serie_changed(self, widg): """Callback when selected UI série changes Actions: * updates the serie Model * then triggers UI update """ itera = widg.get_active_iter() if itera != None: val = widg.get_model().get_value(widg.get_active_iter(), 0) self.serie_model.current_serie = val self.update_serie_view() def put_monitor_on_saison(self): """ Set up monitoring of directory * Installs monitors on current season directory * Installs Callbacks on Season Todo : Refactor to get a "Directory" Model class """ path = self.serie_model.get_current_serie().get_path_to_current_season() self.monitor_serie = None path = Gio.File.new_for_path(path) if(path): self.monitor_serie = path.monitor_directory(Gio.FileMonitorFlags.NONE, None) self.monitor_serie.connect("changed", self.update_subs_and_file) def update_season_number(self, widg): """ Callback when selected Season changes Actions : * update Model * Triggers UI update """ logging.info("saison courante num changed ?") self.serie_model.current_serie.season = int(widg.get_value()) self.update_season_view() self.put_monitor_on_saison() def update_episode_number(self, widg): """ Callback When current episode changes Actions : * updates Model * update UI accordingly """ logging.info("ep courant num changed ?") self.serie_model.current_serie.season.episode = int(widg.get_value()) logging.debug(self.serie_model.current_serie.season.episode.number) self.update_episode_view() def update_skip_time(self, widg): """ Callbacks when user updates the skip time Action : * updates Model """ logging.info("skip time changed ?") self.serie_model.serie.set_skip_time(int(widg.get_value())) def update_decay_time(self, widg): """ Callback when decay time changes Actions: * updates Model """ logging.info("decay time changed ? {}".format(widg.get_value())) self.serie_model.get_current_serie().set_decay_time(int(widg.get_value())) def update_fps(self, widg): """ Callback when User changes the FPS value on the view Action : updates Model TODO: delete or debug """ logging.info("fps time changed ?") val = None logging.info("changed" + val ) self.serie_model.get_current_serie().set_fps(val) def update_subtitle_file(self, widg): """ Callback when user changes selected subtitle file Action : updates Model """ itera = widg.get_active_iter() # logging.info(type(itera), itera) if itera != None: val = widg.get_model().get_value(widg.get_active_iter(), 0) self.serie_model.get_current_serie().set_subtitle_file(val) absolute_subfile = os.path.join( self.serie_model\ .get_current_serie()\ .get_path_to_current_season(), val) subtitle_file_model = ui.subtitles.SubtitlesStore(absolute_subfile) self.app.getitem("SubtitlesTreeView")\ .set_model(subtitle_file_model.get_model()) def update_subs(self): """ Callback The available subtitles are modified Action : updates Model, updtates ui """ liste = self.serie_model.current_serie.season.episode.get_subtitle_list() logging.info("Subs !! nb:{}".format(len(liste))) if len(liste) == 0: self.search_subtitles(None) box = self.app.getitem("CandidateSubsCombo") ui.ui_utils.populate_combo_with_items(box, liste) self.update_subtitle_file(box) def end(self, widg): """ Callback to clean application & exit """ self.player_status.end_player() # Gtk.main_quit(widg) reactor.stop() #pylint: disable = E1101 def video_keypress(self, widgi, event):#pylint: disable=W0613 """ Callback intended to send key events to MPlayer when in a subwindow on the UI TODO : Currently unused, needs a branch. """ logging.info(event.hardware_keycode) #self.player logging.info("keypressed") # logging.info(keyval) def set_manager(self, man): """ Setter for the main Available Séries manager """ self.manager = man