我正在使用vlcj 4.8.0制作一个音乐播放器,并希望实现其MediaDiscovery组件来查找包含音频文件的目录(在本地音乐文件夹中).到目前为止,我一直使用DirectoryChooser和file.listFiles(File::isDirectory)来获取它们,但我认为让MediaDiscoverer来处理这个功能会更实用.

我对this example from vlcj's examples repository做了一些修改,只获得包含音乐文件的目录.

public class MediaDiscovererTest {

    private static final List<String> musicDirectories = new ArrayList<>();

    public static void main(String[] args) throws Exception {

        MediaPlayerFactory factory = new MediaPlayerFactory();
        List<MediaDiscovererDescription> discoverers = factory.mediaDiscoverers().discoverers(MediaDiscovererCategory.LOCAL_DIRS);

        if (discoverers.isEmpty()) {
            return;
        }

        Iterator<MediaDiscovererDescription> iterator = discoverers.iterator();
        while (iterator.hasNext()) {
            MediaDiscovererDescription discoverer = iterator.next();
            if (discoverer.name().equals("picture_dir") || discoverer.name().equals("video_dir")) {
                iterator.remove(); // as I'm only interested in audio directories
            }
        }

        for (MediaDiscovererDescription description : discoverers) {
            final String name = description.name();
            MediaDiscoverer discoverer = factory.mediaDiscoverers().discoverer(name);

            MediaList list = discoverer.newMediaList();

            MediaListEventAdapter mediaListEventAdapter = new MediaListEventAdapter() {
                @Override
                public void mediaListItemAdded(MediaList mediaList, MediaRef item, int index) {
                    Media newMedia = item.newMedia();
                    System.out.println(newMedia.info().mrl());
                    // Adding a new directory to the list
                    musicDirectories.add(newMedia.info().mrl());
                    newMedia.release();
                }
            };

            list.events().addMediaListEventListener(mediaListEventAdapter);

            discoverer.start();
//            list.events().removeMediaListEventListener(mediaListEventAdapter);
//            discoverer.release();
//            list.release();
        }

        System.out.println(musicDirectories.size()); // <- In this test's current state, this will always be 0

        Thread.currentThread().join();

    }

}

每当将新项目合并到MediaList中时,它的路径都会打印到控制台并保存到musicDirecters.这可以达到预期的效果.然而,我不清楚如何监测发现过程的进展.具体地说,我想确定它何时结束,这样我就可以确保我的程序只有在发现过程完成后才能继续进行.

在处理类似的过程时,如解析Media,这是一个异步操作,通过将MediaEventListener附加到MediaPlayer,可以知道解析何时完成:

 mediaPlayer.events().addMediaEventListener(new MediaEventListener() {
@Override
            public void mediaParsedChanged(Media media, MediaParsedStatus newStatus) {
                if (newStatus == MediaParsedStatus.DONE) {
                    // Do something
                }
            }
     });

遗憾的是,我不确定如何为MediaDiscoverer实现这样的方法,因为我已经阅读了它的文档,但找不到任何类似的东西.我有discovered的唯一基本解决方案是在discoverer.start();之后立即使用Thread.sleep(2000),但这显然不是一个理想的方法.是否有更可靠的方法来确定发现过程何时完成?

推荐答案

媒体发现器不断运行,直到它们被停止.

这意味着,至少在原则上,假设你有一个在用户的标准视频目录中查找媒体的媒体发现器,它将发现该目录中的当前项目集,然后在该目录中添加或删除项目时进行更新(引发新事件).

因此,从这个意义上说,这一发现永远不会完成.

实际上,这意味着您的应用程序的编码方式应该能够处理动态变化的媒体列表,而不是固定的列表.

这不像您在发现完成之前停止应用程序,然后呈现发现的项目,更重要的是,您的应用程序有一个动态播放列表,当发现程序添加/删除项目时,该列表不断侦听事件.

当然,您根本不需要使用本地媒体发现器,只需使用普通的Java IO(这就是您最初所做的,这是非常好的),您就可以自己查找包含媒体的标准位置.

Java相关问答推荐

日食IDE 2024-03在Ubuntu下崩溃,导致hr_err_pid.log

虚拟线程似乎在外部服务调用时阻止运营商线程

我可以从Java模块中排除maven资源文件夹吗?

Javascript在边界中心调整ImageView大小

根据对象和值的参数将映射<;T、值&>转换为列表<;T&>

我无法将附件发送到NetBeans之外

Java中如何根据Font.canDisplay方法对字符串进行分段

更新GWT 2.5.1到2.11.0和sencha GXT 3.1.1到4.1时出现错误

将响应转换为带值的键

将Spring Boot 3.2.0升级到3.2.1后查询执行错误

使用Class.this.field=Value初始化构造函数中的最后一个字段会产生错误,而使用this.field=Value则不会

Groovy/Java:匹配带引号的命令选项

如何用内置Java从JavaFX应用程序中生成.exe文件?

A.ForEach与For(类型a:集合)

如何使这两种方法合二为一?

在使用具有不同成本的谓词调用allMatch之前对Java流进行排序会带来什么好处吗?

为什么这种递归会有这样的行为?

活泼的一次判断成语,结果中等

HBox内部的左对齐按钮(如果重要的话,在页码内)

Spring Mapstruct如何获取Lazy初始化实体字段的信息?