FeelUOwn音乐播放器的一点点研究

L4 FeelUOwn音乐播放器

这是python结课作业的第四题(Level 4),选择一个python项目,迁移到自己的机器上(哎就是安装),各路大神都在搞深度学习、人工智能之类,我学习进度没他们快、还没自学到这些,所以选择很受限。很感激遇到这个项目,挺有意思的,让我学到不少。也对着源码发呆没少耗费时光。这是这学期自己探索的最有意思的事了,所以记录一下。

前言:为什么选择这个项目

为什么没有选择实验文档给出的kannan-anbu/python-music-player呢?

一开始选题的时候,我真的不知道该做什么(人工智能、深度学习、数据分析什么都不会),头很大,还没决定要不要做这个播放器的题目,所以只是在github上草率地搜了搜,竟然没找到这个项目,如下图。我还尝试了在github上搜索作者,调整搜索过滤器等方法,都无果。
在这里插入图片描述

随机逛了逛,发现了FeelUOwn这个项目,还是国人写的,3k多星,有自己的项目网站,还配备了开发者指南(当时还不知道不太这个指南不太详细),并公开了开发者交流群,看作者的个人网站(cosven),觉得他是很有哲思的一个人。总而言之,在我为了不知道选什么题目而抓狂之中,这个项目就像一颗启明星。同时,作者是中国人也让我很激动,怎么说呢,看Vue的纪录片时,作者尤雨溪,一个黄皮肤的中国人,做出了风靡全球的开源项目,无论对于web应用从业人员,还是我这种普通学生,这都是一种鼓舞,有一种让人血液里的脉搏更加跳动的力量,而看到FeelUOwn这个国人做的项目,想到我也要和它多少产生点关系,我就不由得激动。

这就是起因。

而直到我准备完了level5的代码,写报告这会儿,才想起来用搜索引擎搜一下那个没搜到的音乐播放器项目,就搜到了…

在这里插入图片描述

现在想来,当时搜不到,大概率是项目及作者名字中的-触发了github搜索的语法,搜索引擎以另外一种方式解析我的搜索内容,才导致搜索不成功。

对这个软件的介绍

这个软件集成了多个音乐平台的的乐库,使用mpv作为默认播放引擎,qt做为gui框架,提供不仅可用而且美观的搜索、播放、歌词等功能,除此之外,还有类似vimrc的配置文件、无GUI启动、与emacs集成等极客的使用内容,有趣也值得探索。

在这里插入图片描述

如何安装并使用

安装

这是官方安装指南

我使用的操作系统是archlinux,所以直接使用命令sudo pacman -S feeluown即可。

而对于其他的linux发行版,安装指南中的pip安装方法应该是比较通用的,我也尝试了,没有问题。

使用

feeluwon既提供gui启动,也支持命令行使用。

安装好后,可以通过命令行启动,也可以通过桌面图标(调用feeluown-genicon生成桌面图标)启动。

阅读源码(link)可以发现,feeluown为自己注册了两个命令行启动别名:fuofeeluown,所以下面我将以方便为主,任意使用两个别名。

gui启动

先尝试启用gui界面:(更新失败是因为垃圾校园网)

在这里插入图片描述

在这个gui界面的上侧可以切换出搜索栏:

在这里插入图片描述

尝试搜索王心凌的爱你, 如下,没有结果:

在这里插入图片描述

这是因为我们还没有安装音乐提供方的插件,作者开发了若干比较流行的音乐提供方插件:网易云、QQ、虾米等(甚至还有集成在vim和emacs中的插件),我在level5中只会涉及网易云插件,所以我们就先安装网易云插件:pip install fuo-netease

安装完成后,重启fuo。

在这里插入图片描述
在这里插入图片描述

可以看到,现在:

  • 左上角出现了网易云的图标

  • 歌曲搜索也有了结果,歌曲最右侧表明音乐来源都是网易云

其他基本的播放,歌词,搜索专辑、歌手等功能,feeluown都有提供,助教不妨多玩一玩。

命令行(daemon)

参考

我们可以在一个端口以纯daemon模式打开feeluown服务,另一个端口使用netcat与其交互,现在的feeluown使用端口23333,以后可能会实现用户指定端口的功能。

在这里插入图片描述

下面是fuo的帮助文本,主要的功能是

play,show,search,remove,add,exec,pause,resume,toggle,stop,next,previous,list,clear,status,genicon

usage: feeluown [-h] [-V] [-ns] [-nw] [-d] [-v] [--log-to-file]
                [--mpv-audio-device MPV_AUDIO_DEVICE]
                {play,show,search,remove,add,exec,pause,resume,toggle,stop,next,previous,list,clear,status,genicon}
                ...

FeelUOwn - modern music player (daemon).

Example:
    - fuo                        # start fuo server
    - fuo status                 # lookup server status
    - fuo play 晴天-周杰伦       # search and play

positional arguments:
  {play,show,search,remove,add,exec,pause,resume,toggle,stop,next,previous,list,clear,status,genicon}
    show                显示资源详细信息
    remove              从播放列表移除歌曲
    add                 添加歌曲到播放列表
    pause               暂停播放
    resume              回复播放
    toggle

options:
  -h, --help            show this help message and exit
  -V, --version         show program's version number and exit
  -ns, --no-server      不运行 server
  -nw, --no-window      不显示 GUI
  -d, --debug           开启调试模式
  -v, --verbose         输出详细的日志
  --log-to-file         将日志打到文件中
  --mpv-audio-device MPV_AUDIO_DEVICE
                        (高级选项)指定播放设备

现在我们尝试通过命令行交互,让feeluown播放张杰唱的夜空中最亮的星。

先看一看当前的播放列表:

list
ACK OK 103
fuo://netease/songs/1474411443    # 爱你 - 王心凌

然后搜索夜空中最亮的星这首歌:

search 夜空中最亮的星-张杰
ACK OK 620
fuo://netease/songs/28427772      # 夜空中最亮的星 (L… - 张杰
fuo://netease/songs/28059417      # 他不懂 - 张杰
fuo://netease/songs/25706282      # 夜空中最亮的星 - 逃跑计划
fuo://netease/songs/574919767     # 只要平凡 - 张杰 & 张碧晨
fuo://netease/songs/191254        # 天下 - 张杰
fuo://netease/songs/1386887580    # 夜空中最亮的星 ( … - 小朱吃了几公斤
fuo://netease/songs/450222627     # 夜空中最亮的星 (l… - 张杰
fuo://netease/songs/570296467     # 粉红色的回忆 + Be… - 张杰 & 六位素人
fuo://netease/songs/1335012479    # 夜空中最亮的星( … - 九艾伦

feeluown的音乐标识符都遵从fuo协议(应该是作者自定义的),也就是这一串:fuo://netease/songs/1405753158,这个代表网易云提供的歌曲,编号为28427772,也就是我们要找的这首歌。我们现在把它添加到播放列表并播放:

add fuo://netease/songs/28427772
ACK OK 0

list
ACK OK 88
fuo://netease/songs/1474411443    # 爱你 - 王心凌
fuo://netease/songs/28427772      #  -
next
ACK OK 0

status
ACK OK 204
   repeat:  true
   random:  false
   volume:  23
    state:  playing
 duration:  372.532245
 position:  4.320552399092971
     song:  fuo://netease/songs/28427772    #  -
  lyric-s:   作曲 : 逃跑计划

这里看到程序的一个小bug,添加之后没有歌曲信息。因为现在播放的还是爱你 这首歌,所以我们使用next命令播放下一首的夜空中最亮的星。随着音乐响起,我们可以用status查看,播放的是fuo://netease/songs/28427772,无误。

在server的终端Ctrl-C关闭服务端。关闭不当会导致端口23333仍被占用,不能重新打开feeluown,linux下需要使用kill -s KILL {fuo/feeluown}杀掉后台进程。

配置文件

在用户目录下的.fuorc就是配置文件,这是一个py文件。feeluown会暴露config对象和若干函数到这个文件中,并在启动时以python的exec方法执行它。

一些可配置项可以在这里找到。

对于自定义函数这项,add_hook源码是这样的:

@expose_to_rcfile(aliases='when')
def add_hook(signal_symbol: str, func: Callable, use_symbol: bool = False, **kwargs):
    """add hook on signal

    :param signal_symbol: app.{object}.{signal_name} .
    :param func: Signal receiver.
    :param use_symbol: Whether to connect the signal to the symbol of the receiver.
        If this is true, the real receiver is lazy found by the symbol, and
        the signal connects to a symbol instead of a function object.
        If this is false, problem may occur when the rcfile is reloaded.
        because there the signal connects to two *same* receivers.
    :param kwargs: This is directly passed to Signal.connect.

    >>> def func(): pass
    >>> add_hook('app.initialized', func)

    .. versionadded:: 3.8
       The *kwargs* keyword argument.
    """
    signal_mgr.add(signal_symbol, func, use_symbol, **kwargs)

暴露到配置文件是由一个装饰器实现的,有个alias:when,比较重要的是signal_symbol这个参数的格式:app.{object}.{signal_name}

以作者提供的一个示例为例:

when('app.playlist.song_changed', notify_song_changed)

notify_song_changed就是自定义的函数,我们来看这个'app.playlist.song_changed',这个代表的是当播放列表歌曲发生切换时的signal。这种信号可以在源码中找到,我的意思是,作者没有提供所有信号的列表。以这个信号为例,在这里找到,类似的,也可以找到playerlist的若干其他信号(考虑到继承后的实现,这个列表不一定全):

SignalMeaning
eof_reachedplaylist have no enough songs
mode_changedplaylist mode changed signal
playback_mode_changedplayback mode changed signal
songs_addedadd a song
songs_removedreomove a song
song_changedchange a song
song_changed_v2don’t know what it’s

自定义函数先讨论到这里,再看config对象,这个可定义项我拷贝了下来,是这样的:

名称类型默认值描述
DEBUGboolFalse是否为调试模式
MODEstr0x0000CLI or GUI 模式
THEMEstrautoauto/light/dark
COLLECTIONS_DIRstr''本地收藏所在目录
LOG_TO_FILEboolTrue将日志输出到文件中
AUDIO_SELECT_POLICYstrhq<>feeluown.media.Quality.SortPolicy
VIDEO_SELECT_POLICYstrhd<>feeluown.media.Quality.SortPolicy

我想配置的只有主题,其实主题还有一个选项:`macos_dark’,可以在这里找到。

为什选用这个主题呢?因为dark主题只有底端是黑色的,主面板还是白的💢

所有的都介绍完了,更新一下配置文件:

config.THEME = 'macos_dark'

# 一个小功能:切换歌曲时,发送系统通知
def notify_song_changed(song):
    if song is not None:
        title = song.title_display
        artists_name = song.artists_name_display
        song_str = f'{title}-{artists_name}'
        #  os.system(f'notify-send "{song_str}"')
        print(f"{song_str}")


when('app.playlist.song_changed', notify_song_changed)

# 让编辑器识别这是一个 Python 文件
#
# Local Variables:
# mode: python
# End:
#
# vim: ft=python

这时通过命令行启动fuo,看到黑色主题来了,在切换歌曲时,启动终端会发出切换歌曲通知:

在这里插入图片描述

更多配置:

本应该可以像notify_song_changed一样,定义添加、删除歌曲的hook函数,但是这并不现实。拿songs_added为例,注意这个Signal的名称中是songs而不是song,因为可能批量增加,这时hook函数的参数不再是song而是:(idx, cnt),代表增加在列表中的起始位置和增加个数。有这些信息,可是我没有运行时的app实例呀!如果考虑修改源码,那不是不行,但是没必要。

但是其他的配置函数,有需要还是可以考虑一下的,比如eof_reached就不要参数,这个好,我们可以在播放列表到达末尾时给发送一条消息。就简单地给终端发送一条信息,可以参考这样的写法:

when('app.playlist.eof_reached', notify_eof)
def notify_eof():
    print("EOF reached")

我担心助教说我做无用功,所以解释一下为啥费这么大功夫搞这玩意:

这些配置文件都是简化版的模型,我想,像fuorc这样比较贴近源码的配置文件,配置好了是可以有很多实用、高度定制化的玩法的。

就拿这个eof来说,顺序播放在到达列表末端时会停止播放,这时提醒一下播放结束了,不用让听的人纠结:是不是还在加载新歌曲呢?我的naive实现只在daemon模式下有效,但是完全可以将这个hook函数写复杂一点,比如:向窗口管理器发送通知,使标签页显红闪烁,像这种:

在这里插入图片描述
在这里插入图片描述
所以我做的这些工作/研究还是有实用价值的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值