def __init__(self): # create cache and config directories try: os.makedirs(dirs.user_cache_dir) except OSError as e: if not os.path.isdir(dirs.user_cache_dir): raise try: os.makedirs(dirs.user_config_dir) except OSError as e: if not os.path.isdir(dirs.user_config_dir): raise # open config file self.config = Config(os.path.join(dirs.user_config_dir, config_file)) self.config.read() # configure cache region.configure('dogpile.cache.dbm', expiration_time=timedelta(days=30), arguments={ 'filename': os.path.join(dirs.user_cache_dir, cache_file), 'lock_factory': MutexLock })
def __init__(self): # create app directory try: os.makedirs(app_dir) except OSError: if not os.path.isdir(app_dir): raise # open config file self.config = Config(os.path.join(app_dir, config_file)) self.config.read() # configure cache region.configure('dogpile.cache.dbm', expiration_time=timedelta(days=30), arguments={'filename': os.path.join(app_dir, cache_file), 'lock_factory': MutexLock})
class SubliminalExtension(GObject.GObject, Nautilus.MenuProvider): def __init__(self): # create app directory try: os.makedirs(app_dir) except OSError: if not os.path.isdir(app_dir): raise # open config file self.config = Config(os.path.join(app_dir, config_file)) self.config.read() # configure cache region.configure('dogpile.cache.dbm', expiration_time=timedelta(days=30), arguments={'filename': os.path.join(app_dir, cache_file), 'lock_factory': MutexLock}) def get_file_items(self, window, files): # lightweight filter on file type and extension if not any(f.is_directory() or f.get_name().endswith(VIDEO_EXTENSIONS) for f in files): return # create subliminal menu subliminal_menuitem = Nautilus.MenuItem(name='SubliminalMenu::Subliminal', label='Subliminal') sub_menus = Nautilus.Menu() subliminal_menuitem.set_submenu(sub_menus) # create choose submenu on single file if len(files) == 1 and not files[0].is_directory(): choose_menuitem = Nautilus.MenuItem(name='SubliminalSubMenu::Choose', label=_('Choose subtitles')) choose_menuitem.connect('activate', self.choose_callback, files) sub_menus.append_item(choose_menuitem) # create download submenu download_menuitem = Nautilus.MenuItem(name='SubliminalSubMenu::Download', label=_('Download subtitles')) download_menuitem.connect('activate', self.download_callback, files) sub_menus.append_item(download_menuitem) # create configure submenu configure_menuitem = Nautilus.MenuItem(name='SubliminalSubMenu::Configure', label=_('Configure...')) configure_menuitem.connect('activate', self.config_callback) sub_menus.append_item(configure_menuitem) return subliminal_menuitem, def get_background_items(self, window, current_folder): return [] def choose_callback(self, menuitem, files): # scan the video video = scan_video(files[0].get_location().get_path(), subtitles=False, embedded_subtitles=False) # load the interface builder = Gtk.Builder() builder.set_translation_domain('subliminal') builder.add_from_file(os.path.join(os.path.dirname(__file__), 'subliminal', 'ui', 'choose.glade')) # set the video filename video_filename = builder.get_object('video_filename_label') video_filename.set_text(files[0].get_name()) # start the spinner spinner = builder.get_object('spinner') spinner.start() def _list_subtitles(): # list subtitles with ProviderPool(providers=self.config.providers, provider_configs=self.config.provider_configs) as pool: subtitles = pool.list_subtitles(video, self.config.languages) # fill the subtitle liststore subtitle_liststore = builder.get_object('subtitle_liststore') for s in subtitles: matches = s.get_matches(video, hearing_impaired=self.config.hearing_impaired) scaled_score = compute_score(matches, video) if s.hearing_impaired == self.config.hearing_impaired: scaled_score -= video.scores['hearing_impaired'] scaled_score *= 100 / video.scores['hash'] subtitle_liststore.append([s.id, nice_language(s.language), scaled_score, s.provider_name.capitalize(), s.hearing_impaired, s.page_link, False]) subtitle_liststore.set_sort_column_id(2, Gtk.SortType.DESCENDING) # stop the spinner spinner.stop() # connect signals builder.connect_signals(ChooseHandler(self.config, video, subtitles, spinner)) threading.Thread(target=_list_subtitles).start() # display window window = builder.get_object('subtitle_window') window.show_all() Gtk.main() def download_callback(self, menuitem, files): # scan videos videos = [] for f in files: # ignore non-writable locations if not f.can_write(): continue # directories if f.is_directory(): try: scanned_videos = scan_videos(f.get_location().get_path(), subtitles=True, embedded_subtitles=self.config.embedded_subtitles) except: continue for video in scanned_videos: if check_video(video, languages=self.config.languages, age=self.config.age, undefined=self.config.single): videos.append(video) continue # other inputs try: video = scan_video(f.get_location().get_path(), subtitles=True, embedded_subtitles=self.config.embedded_subtitles) except: continue if check_video(video, languages=self.config.languages, undefined=self.config.single): videos.append(video) # download best subtitles downloaded_subtitles = defaultdict(list) with ProviderPool(providers=self.config.providers, provider_configs=self.config.provider_configs) as pool: for v in videos: subtitles = pool.download_best_subtitles( pool.list_subtitles(v, self.config.languages - v.subtitle_languages), v, self.config.languages, min_score=v.scores['hash'] * self.config.min_score / 100, hearing_impaired=self.config.hearing_impaired, only_one=self.config.single ) downloaded_subtitles[v] = subtitles # save subtitles for v, subtitles in downloaded_subtitles.items(): save_subtitles(v, subtitles, single=self.config.single) def config_callback(self, *args, **kwargs): # load the interface builder = Gtk.Builder() builder.set_translation_domain('subliminal') builder.add_from_file(os.path.join(os.path.dirname(__file__), 'subliminal', 'ui', 'config.glade')) # configure the about page aboutdialog = builder.get_object('aboutdialog') aboutdialog.set_version(__version__) aboutdialog.set_copyright(__copyright__) aboutdialog.vbox.reparent(builder.get_object('about_box')) # fill the language liststore available_languages = set() for provider in provider_manager: available_languages |= provider.plugin.languages language_liststore = builder.get_object('language_liststore') for language in sorted(available_languages - ignored_languages, key=nice_language): language_liststore.append([nice_language(language), str(language)]) # set language selection language_treeselection = builder.get_object('language_treeselection') for language in language_liststore: if Language.fromietf(language[1]) in self.config.languages: language_treeselection.select_path(language.path) # fill the provider liststore provider_liststore = builder.get_object('provider_liststore') for provider in sorted([p.name for p in provider_manager]): provider_liststore.append([provider.capitalize(), str(self.config.provider_configs.get(provider, ''))]) # set provider selection provider_treeselection = builder.get_object('provider_treeselection') for provider in provider_liststore: if provider[0].lower() in self.config.providers: provider_treeselection.select_iter(provider.iter) # set single state single_switch = builder.get_object('single_switch') single_switch.set_active(self.config.single) # set embedded subtitles state embedded_subtitles_switch = builder.get_object('embedded_subtitles_switch') embedded_subtitles_switch.set_active(self.config.embedded_subtitles) # set age value age_spinbutton = builder.get_object('age_spinbutton') age_spinbutton.set_value(self.config.age.days) # set hearing impaired state hearing_impaired_switch = builder.get_object('hearing_impaired_switch') hearing_impaired_switch.set_active(self.config.hearing_impaired) # set min score value min_score_spinbutton = builder.get_object('min_score_spinbutton') min_score_spinbutton.set_value(self.config.min_score) # connect signals builder.connect_signals(ConfigHandler(self.config)) # display window window = builder.get_object('config_window') window.show_all() Gtk.main()
class SubliminalExtension(GObject.GObject, Nautilus.MenuProvider): def __init__(self): # create cache and config directories try: os.makedirs(dirs.user_cache_dir) except OSError as e: if not os.path.isdir(dirs.user_cache_dir): raise try: os.makedirs(dirs.user_config_dir) except OSError as e: if not os.path.isdir(dirs.user_config_dir): raise # open config file self.config = Config(os.path.join(dirs.user_config_dir, config_file)) self.config.read() # configure cache region.configure('dogpile.cache.dbm', expiration_time=timedelta(days=30), arguments={ 'filename': os.path.join(dirs.user_cache_dir, cache_file), 'lock_factory': MutexLock }) def get_file_items(self, window, files): # lightweight filter on file type and extension if not any(f.is_directory() or f.get_name().endswith(VIDEO_EXTENSIONS) for f in files): return # create subliminal menu subliminal_menuitem = Nautilus.MenuItem( name='SubliminalMenu::Subliminal', label='Subliminal') sub_menus = Nautilus.Menu() subliminal_menuitem.set_submenu(sub_menus) # create choose submenu on single file if len(files) == 1 and not files[0].is_directory(): choose_menuitem = Nautilus.MenuItem( name='SubliminalSubMenu::Choose', label=_('Choose subtitles')) choose_menuitem.connect('activate', self.choose_callback, files) sub_menus.append_item(choose_menuitem) # create download submenu download_menuitem = Nautilus.MenuItem( name='SubliminalSubMenu::Download', label=_('Download subtitles')) download_menuitem.connect('activate', self.download_callback, files) sub_menus.append_item(download_menuitem) # create configure submenu configure_menuitem = Nautilus.MenuItem( name='SubliminalSubMenu::Configure', label=_('Configure...')) configure_menuitem.connect('activate', self.config_callback) sub_menus.append_item(configure_menuitem) return subliminal_menuitem, def get_background_items(self, window, current_folder): return [] def choose_callback(self, menuitem, files): # scan the video video = scan_video(files[0].get_location().get_path()) refine(video, episode_refiners=self.config.refiners, movie_refiners=self.config.refiners, embedded_subtitles=False) # load the interface builder = Gtk.Builder() builder.set_translation_domain('subliminal') builder.add_from_file( os.path.join(os.path.dirname(__file__), 'subliminal', 'ui', 'choose.glade')) # set the video filename video_filename = builder.get_object('video_filename_label') video_filename.set_text(files[0].get_name()) # start the spinner spinner = builder.get_object('spinner') spinner.start() def _list_subtitles(): # list subtitles with AsyncProviderPool( providers=self.config.providers, provider_configs=self.config.provider_configs) as pool: subtitles = pool.list_subtitles(video, self.config.languages) # fill the subtitle liststore subtitle_liststore = builder.get_object('subtitle_liststore') for s in subtitles: scaled_score = compute_score(s, video) scores = get_scores(video) if s.hearing_impaired == self.config.hearing_impaired: scaled_score -= scores['hearing_impaired'] scaled_score *= 100 / scores['hash'] subtitle_liststore.append([ s.id, nice_language(s.language), scaled_score, s.provider_name.capitalize(), s.hearing_impaired, s.page_link, False ]) subtitle_liststore.set_sort_column_id(2, Gtk.SortType.DESCENDING) # stop the spinner spinner.stop() # connect signals builder.connect_signals( ChooseHandler(self.config, video, subtitles, spinner)) threading.Thread(target=_list_subtitles).start() # display window window = builder.get_object('subtitle_window') window.show_all() Gtk.main() def download_callback(self, menuitem, files): # scan videos videos = [] for f in files: # ignore non-writable locations if not f.can_write(): continue # directories if f.is_directory(): try: scanned_videos = scan_videos(f.get_location().get_path()) except: continue for video in scanned_videos: if check_video(video, languages=self.config.languages, age=self.config.age, undefined=self.config.single): video.subtitle_languages |= set( search_external_subtitles(video.name).values()) refine( video, episode_refiners=self.config.refiners, movie_refiners=self.config.refiners, embedded_subtitles=self.config.embedded_subtitles) videos.append(video) continue # other inputs try: video = scan_video(f.get_location().get_path()) except: continue if check_video(video, languages=self.config.languages, undefined=self.config.single): video.subtitle_languages |= set( search_external_subtitles(video.name).values()) refine(video, episode_refiners=self.config.refiners, movie_refiners=self.config.refiners, embedded_subtitles=self.config.embedded_subtitles) videos.append(video) # download best subtitles downloaded_subtitles = defaultdict(list) with AsyncProviderPool( providers=self.config.providers, provider_configs=self.config.provider_configs) as pool: for v in videos: scores = get_scores(v) subtitles = pool.download_best_subtitles( pool.list_subtitles( v, self.config.languages - v.subtitle_languages), v, self.config.languages, min_score=scores['hash'] * self.config.min_score / 100, hearing_impaired=self.config.hearing_impaired, only_one=self.config.single) downloaded_subtitles[v] = subtitles # save subtitles for v, subtitles in downloaded_subtitles.items(): save_subtitles(v, subtitles, single=self.config.single) def config_callback(self, *args, **kwargs): # load the interface builder = Gtk.Builder() builder.set_translation_domain('subliminal') builder.add_from_file( os.path.join(os.path.dirname(__file__), 'subliminal', 'ui', 'config.glade')) # configure the about page aboutdialog = builder.get_object('aboutdialog') aboutdialog.set_version(__version__) aboutdialog.set_copyright(__copyright__) aboutdialog.vbox.reparent(builder.get_object('about_box')) # fill the language liststore available_languages = set() for provider in provider_manager: available_languages |= provider.plugin.languages language_liststore = builder.get_object('language_liststore') for language in sorted(available_languages - ignored_languages, key=nice_language): language_liststore.append([nice_language(language), str(language)]) # set language selection language_treeselection = builder.get_object('language_treeselection') for language in language_liststore: if Language.fromietf(language[1]) in self.config.languages: language_treeselection.select_path(language.path) # fill the provider liststore provider_liststore = builder.get_object('provider_liststore') for provider in sorted([p.name for p in provider_manager]): provider_liststore.append([ provider.capitalize(), str(self.config.provider_configs.get(provider, '')) ]) # set provider selection provider_treeselection = builder.get_object('provider_treeselection') for provider in provider_liststore: if provider[0].lower() in self.config.providers: provider_treeselection.select_iter(provider.iter) # fill the refiner liststore refiner_liststore = builder.get_object('refiner_liststore') for refiner in sorted([r.name for r in refiner_manager], key=lambda r: (r not in self.config.refiners, r)): refiner_liststore.append([refiner.capitalize()]) # set refiner selection refiner_treeselection = builder.get_object('refiner_treeselection') for refiner in refiner_liststore: if refiner[0].lower() in self.config.refiners: refiner_treeselection.select_iter(refiner.iter) # set single state single_switch = builder.get_object('single_switch') single_switch.set_active(self.config.single) # set embedded subtitles state embedded_subtitles_switch = builder.get_object( 'embedded_subtitles_switch') embedded_subtitles_switch.set_active(self.config.embedded_subtitles) # set age value age_spinbutton = builder.get_object('age_spinbutton') age_spinbutton.set_value(self.config.age.days) # set hearing impaired state hearing_impaired_switch = builder.get_object('hearing_impaired_switch') hearing_impaired_switch.set_active(self.config.hearing_impaired) # set min score value min_score_spinbutton = builder.get_object('min_score_spinbutton') min_score_spinbutton.set_value(self.config.min_score) # connect signals builder.connect_signals(ConfigHandler(self.config)) # display window window = builder.get_object('config_window') window.show_all() Gtk.main()