我正在使用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相关问答推荐

在AnyLogic中增加变量计数

JVM会优化这个数学运算吗?

如何找到MongoDB文档并进行本地化?

在运行MVN测试时,为什么构建失败,并显示了java.lang.ClassNotFoundException:java.net.http.HttpResponse?

测试期间未执行开放重写方法

测试容器无法加载类路径初始化脚本

如何在Java记录中设置BigDecimal类型属性的精度?

如何仅使用键/ID的一部分(组合)高效地返回映射值?

在学习Spring时,通过构造函数参数0表达了不满意的依赖关系

在macOS上读取文件会导致FileNotFound,即使文件存在(并且具有权限)

如何在太阳系模拟器中添加月球?

嘲笑黄瓜中的对象

用于Java的Visual Studio代码完成不起作用

验证没有';t work on Hibernate Entity';s字段

Java返回生成器的实现

AspectJ编织外部依赖代码,重新打包jar并强制依赖用户使用它

由于版本不匹配,从Java 8迁移到Java 17和Spring 6 JUnit4失败

人们在 IntelliJ 上将-Dhttp.proxyHost=your.proxy.net -Dhttp.proxyPort=8080放在哪里?

为什么方法接受协变类型的匿名泛型类对象?

Hibernate 6 + 类的属性持久化为字符串