Example #1
0
    def start(self):
        alang = Config.get("player", "preferred audio", default="eng")
        slang = Config.get("player", "preferred subtitle", default="eng")
        vo = Config.get("player", "video output", default="vdpau,opengl-hq,x11,opengl")
        self.player = VideoPlayer(alang=alang, slang=slang, vo=vo, fs="yes")

        asyncio.async(self.update_per_second())
        asyncio.async(self.event_listener())

        yield from websockets.serve(self.handle_websocket, "0.0.0.0", 5002)
Example #2
0
    def update_track_info(self):
        yield from asyncio.gather(
            self.broadcast_available_subtitles(),
            self.broadcast_available_audio(),
            self.broadcast_subtitle(),
            broadcast_player_property("selected_audio", str(self.audio)),
            events.broadcast("list-subtitles", path=self.client.path),
        )

        if (
            self.sub != 0
            and self.audio_language() != "unk"
            and self.audio_language() == self.sub_language()
            and not int(Config.get("player", "subtitles for matching audio"))
        ):
            log.info("Disabling subtitle as it's the same as the language")
            self.client.sub = 0
Example #3
0
parser = argparse.ArgumentParser()
parser.add_argument(
    '--log-level',
    default='INFO',
    help="Log Level. Must be one of CRITICAL, ERROR, WARNING, INFO or DEBUG")

options = parser.parse_args()

try:
    setup_logging('aesop.processor', 'INFO')
except LookupError:
    parser.error("--log-level must be one of CRITICAL, ERROR, WARNING, INFO or DEBUG")

init()

max_lookups = int(Config.get('processor', 'concurrency', default=50))

sources = list(Source.select(Source.path, Source.type))

events.info.blocking("Starting scan")
log.info("Starting scan")

total = unscanned = removed = 0
for source in sources:
    t, u, r = catalog_videos(database_proxy, source, max_lookups)

    total += t
    unscanned += u
    removed += r

msg = "Scan complete. {} new items, {} could not be added. {} items were removed from the db".format(total, unscanned, removed)
Example #4
0
 def ws_seek_backward(self):
     seek_size = int(Config.get("player", "seek size", default=15))
     self.player.seek_backward(seek_size)
Example #5
0
def catalog_videos(database, source, max_lookups):
    from aesop.processor.movie import MovieLookup
    from aesop.processor.episode import AnimeLookup, TVShowLookup

    model, lookup_model = {
        'movies': (Movie, MovieLookup),
        'tv': (TVShow, TVShowLookup),
        'anime': (TVShow, AnimeLookup),
    }[source.type]

    log.info("Cataloguing {} videos for {}", source.type, source.path)

    if model == Movie:
        query = model.select(model.path)
        known_paths = set(itertools.chain.from_iterable(m.path.split('|') for m in query))
    else:
        query = TVShowEpisode.select(TVShowEpisode.path).where(TVShowEpisode.path.startswith(source.path))
        known_paths = {m.path for m in query}

    known_video_types = set(Config.get('processor', 'video types', default='avi, mp4, mkv, ogm').replace(' ', '').split(','))

    lookups = []
    paths = []

    log.debug("Known paths {}", known_paths)

    removed = 0

    for path in set(known_paths):
        if not os.path.exists(path):
            known_paths.remove(path)
            log.info("{} does not exist, removing from database.", path)
            if model == Movie:
                Movie.delete().where(
                    (Movie.path == path) |
                    Movie.path.contains(path+'|') |
                    Movie.path.contains('|'+path)
                ).execute()
            else:
                ep = TVShowEpisode.select().where(TVShowEpisode.path == path).get()

                show = ep.show

                removed += 1

                with database_proxy.transaction():
                    ep.delete_instance()

                    if not list(show.episodes):
                        show.delete_instance()
                    else:
                        if all([episode.watched for episode in show.episodes]):
                            show.watched = True
                            if show.is_dirty():
                                show.save()

    start_time = time.time()
    successes = 0
    lookup_failures = 0

    for root, dirs, files in os.walk(source.path):
        for path in (os.path.join(root, p) for p in files):
            if '/.AppleDouble/' in path:
                log.debug('Skipping {} as it looks like an Apple double.', path)
                continue

            if os.path.basename(path).startswith('.'):
                continue

            if os.path.splitext(path)[1][1:] not in known_video_types:
                continue

            if '/sample/' in path.lower() or os.path.splitext(path)[0].lower().endswith('-sample'):
                log.debug('Skipping {} as it looks like a sample.', path)
                continue

            if path in known_paths:
                continue

            with FingersCrossedHandler(default_handler):
                try:
                    path_lookups = lookup_model.from_path(path)
                except SkipIt as e:
                    log.error("Skipping path: {} {}", path, str(e))
                except Exception as e:
                    lookup_failures += 1
                    exception = ''.join(traceback.format_exception(e.__class__, e, e.__traceback__))
                    log.error("Error retrieving information for {}: {}", path, exception)
                else:
                    lookups.extend(path_lookups)
                    paths.extend([path]*len(path_lookups))

    loop = asyncio.get_event_loop()

    log.info("{} lookups to do", len(lookups))

    for i in range(0, len(lookups), max_lookups):
        chunk = lookups[i:i+max_lookups]
        f = asyncio.gather(
                *[asyncio.async(c, loop=loop) for c in chunk],
                loop=loop, return_exceptions=True)
        completed = loop.run_until_complete(f)

        with database.transaction():
            for path, lookup in zip(paths[i:i+max_lookups], completed):
                if isinstance(lookup, SkipIt):
                    # logged earlier, no need to log now
                    lookup_failures += 1
                elif isinstance(lookup, Exception):
                    lookup_failures += 1
                    exception = ''.join(traceback.format_exception(lookup.__class__, lookup, lookup.__traceback__))

                    log.error("Error retrieving information for {}: {}", path, exception)
                else:
                    genres = [Genre.get_or_create(text=g) for g in lookup.genres]
                    if source.type == 'movies':
                        save_movie(lookup, path, genres)
                    else:
                        save_episode(lookup, path, genres, source.type)

                    successes += 1
    end_time = time.time()

    log.info("Took {:.2f} seconds to do {} lookups", end_time - start_time, len(lookups))
    log.info("{} lookups failed", lookup_failures)

    return successes, lookup_failures, removed