Exemple #1
0
def test_SimpleConvertTask_can_keep_or_remove_album_art(tmp_path):
    """SimpleConvertTask can convert an audio file"""
    src = tmp_path.joinpath("sine.flac")
    mp3_art = tmp_path.joinpath("sine_art.mp3")
    mp3_noart = tmp_path.joinpath("sine_noart.mp3")
    ogg_art = tmp_path.joinpath("sine_art.ogg")
    ogg_noart = tmp_path.joinpath("sine_noart.ogg")

    sound = generators.Sine(440).to_audio_segment()
    sound.export(src, format="flac")

    # setup a source flac file with a cover image
    image_file = _utils.get_project_root().joinpath("tests/data/cover.jpg")
    with open(image_file, 'rb') as f:
        cover = f.read()
        cover = mediafile.Image(data=cover,
                                desc=u'album cover',
                                type=mediafile.ImageType.front)
    f = MediaFile(src)
    f.images = [cover]
    f.save()

    # by default, the converters preserve the album art
    # .. for PydubConverter
    tasks.SimpleConvertTask(src,
                            mp3_art,
                            converter=converters.PydubConverter()).start()
    g = MediaFile(mp3_art)
    assert f.images[0].data == cover.data
    assert f.images[0].mime_type == 'image/jpeg'
    assert f.images[0].data == g.images[0].data

    # ... for PydubConverter
    tasks.SimpleConvertTask(src,
                            ogg_art,
                            converter=converters.PydubConverter()).start()
    g = MediaFile(ogg_art)
    assert f.images[0].data == cover.data
    assert f.images[0].mime_type == 'image/jpeg'
    assert f.images[0].data == g.images[0].data

    # remove_art=True removes art
    # ... for PydubConverter
    tasks.SimpleConvertTask(
        src, mp3_noart,
        converter=converters.PydubConverter(remove_art=True)).start()
    g = MediaFile(mp3_noart)
    assert f.images[0].data == cover.data
    assert g.images == []

    # remove_art=True removes art
    # ... for PydubConverter
    tasks.SimpleConvertTask(
        src, ogg_noart,
        converter=converters.PydubConverter(remove_art=True)).start()
    g = MediaFile(ogg_noart)
    assert f.images[0].data == cover.data
    assert g.images == []
Exemple #2
0
def test_SimpleConvertTask_passes_on_params(tmp_path):
    """ConvertTask can convert an audio file in a two-step process"""
    src = tmp_path.joinpath("sine.flac")
    dst_lq = tmp_path.joinpath("sine-lq.mp3")
    dst_hq = tmp_path.joinpath("sine-hq.mp3")

    sound = generators.Sine(440).to_audio_segment()
    sound.export(src, format="flac")

    tasks.SimpleConvertTask(
        src,
        dst_lq,
        converter=converters.PydubConverter(parameters=['-q:a', '9'])).start()
    assert dst_lq.exists()

    tasks.SimpleConvertTask(
        src,
        dst_hq,
        converter=converters.PydubConverter(parameters=['-q:a', '0'])).start()
    assert dst_hq.exists()

    assert src.exists()
    assert MediaFile(dst_lq).bitrate < MediaFile(dst_hq).bitrate
Exemple #3
0
def test_SimpleConvertTask(tmp_path):
    """SimpleConvertTask can convert an audio file"""
    src = tmp_path.joinpath("sine.flac")
    dst = tmp_path.joinpath("sine.mp3")

    sound = generators.Sine(440).to_audio_segment()
    sound.export(src, format="flac")

    tsk = tasks.SimpleConvertTask(src,
                                  dst,
                                  converter=converters.PydubConverter())
    tsk.start()

    assert src.exists()
    assert dst.exists()
Exemple #4
0
def test_TaskQueue_can_run_convert_tasks(tmp_path):
    """Ensure all TaskQueue transfer and convert processes are closed after the queue finishes processing all tasks"""

    # test this on a ConvertTask because that launches additional processes that we also want to ensure are shut down
    sound = generators.Sine(440).to_audio_segment()
    src = tmp_path.joinpath("sine.flac")
    dst = tmp_path.joinpath("sine.mp3")

    sound.export(src, format="flac")
    q = tasks.TaskQueue(tmp_path.joinpath("qop.db"))
    q.put(tasks.ConvertTask(src, dst, converter=converters.PydubConverter()))
    q.start()
    wait_for_queue(q)

    assert src.exists()
    assert dst.exists()
    assert q.n_active == 0
    assert q.active_processes() == 0
Exemple #5
0
def test_ConvertTask(tmp_path):
    """ConvertTask can convert an audio file in a two-step process"""
    src = tmp_path.joinpath("sine.flac")
    dst = tmp_path.joinpath("sine.mp3")

    sound = generators.Sine(440).to_audio_segment()
    sound.export(src, format="flac")

    tsk = tasks.ConvertTask(src,
                            dst,
                            converter=converters.PydubConverter(),
                            tempdir=tmp_path)
    tsk.start()
    assert src.exists()
    assert not dst.exists()

    # mock `oid` that is used to match a task to its follow_up_task under production conditions. oid fulfils no function
    # if the follow_up_task is not executed by a TaskQueue.
    tsk.oid = 1
    tsk.spawn().start()
    assert src.exists()
    assert dst.exists()
Exemple #6
0
def handle_copy_convert_move(args, client) -> Dict:
    sources = args.paths[:-1]
    dst_dir = Path(args.paths[-1]).resolve()
    is_queue_active = client.is_queue_active()

    assert isinstance(dst_dir, Path)
    assert len(sources) > 0
    assert sources != dst_dir

    # for use by `qop re`
    args_cache = Path(
        appdirs.user_cache_dir('qop')).joinpath('last_args.pickle')
    if args_cache.exists():
        args_cache.unlink()
    with open(args_cache, 'wb') as f:
        args.parser = None
        pickle.dump(args, f, pickle.HIGHEST_PROTOCOL)

    # setup scanner
    if args.include is not None:
        scanner = scanners.IncludeScanner(args.include)
    elif args.exclude is not None:
        scanner = scanners.ExcludeScanner(args.exclude)
    elif args.mode == "convert":
        scanner = scanners.Scanner()
    else:
        scanner = scanners.PassScanner()

    # setup converter (if necessary)
    if args.mode == "convert":
        conv = converters.PydubConverter(remove_art=args.remove_art,
                                         parameters=args.parameters)  # TODO
        conv_copy = converters.CopyConverter(remove_art=args.remove_art)

        if args.convert_only is not None:
            conv_mode = "include"
            conv_exts = ["." + e for e in args.convert_only]
        elif args.convert_not is not None:
            conv_mode = "exclude"
            conv_exts = ["." + e for e in args.convert_not]
        elif args.convert_none:
            conv_mode = "none"
            conv_exts = None
        else:
            conv_mode = "all"
            conv_exts = None
    else:
        conv_mode = None
        conv_exts = None
        conv = None
        conv_copy = None

    for source in sources:
        root = Path(source).resolve().parent
        children = scanner.scan(source)

        for src in children:
            lg.debug(f"inserting {src}")
            src = Path(src).resolve()
            dst = Path(dst_dir).resolve().joinpath(src.relative_to(root))

            # setup convert task
            if args.mode == "convert":
                if conv_mode == "all":
                    dst = dst.with_suffix("." + conv.ext)
                    tsk = tasks.ConvertTask(src=src, dst=dst, converter=conv)
                elif conv_mode == "include" and src.suffix in conv_exts:
                    dst = dst.with_suffix("." + conv.ext)
                    tsk = tasks.ConvertTask(src=src, dst=dst, converter=conv)
                elif conv_mode == "exclude" and src.suffix not in conv_exts:
                    dst = dst.with_suffix("." + conv.ext)
                    tsk = tasks.ConvertTask(src=src, dst=dst, converter=conv)
                elif args.remove_art:
                    tsk = tasks.SimpleConvertTask(src=src,
                                                  dst=dst,
                                                  converter=conv_copy)
                else:
                    tsk = tasks.CopyTask(src=src, dst=dst)
            elif args.mode == "move":
                tsk = tasks.MoveTask(src=src, dst=dst)
            elif args.mode == "copy":
                tsk = tasks.CopyTask(src=src, dst=dst)
            else:
                raise ValueError

            rsp = client.send_command(Command.QUEUE_PUT, payload=tsk)

            if not is_queue_active and not args.enqueue_only:
                client.send_command(Command.QUEUE_START)
                is_queue_active = True

            if args.verbose:
                print(format_response(rsp))

            print(format_response_summary(client.stats), end="\r")

    if not args.enqueue_only:
        client.send_command(Command.QUEUE_START)
    return {"status": Status.OK, "msg": "enqueue finished"}