香蕉派+悦读fm:打造红外遥控FM播放器(续)

前面的香蕉派+悦读fm:打造红外遥控FM播放器讲了怎么使用红外遥控。当时留了一个接下来的任务。这两天弄完并经过长时间的验证,觉得尚可行。那么回家前就说说怎么增加按键控制和频道选择吧

安装mplayer

之前用的是mpg123。虽然mpg123有个命令参数-C可以进行基本的音量控制,播放控制等操作,但是无奈它并不支持PIPE控制,因此python.subprocess也就派不上用场。而虽然它还有一个参数-R配合--fifo可以进行远程操作,也就是PIPE可用。但还有个问题,在这种远程操作模式下可用命令是非常有限的,其实就没有我想要的可以上下切音频的命令。因此,转而用mplayer。

MPlayer有一个参数-slave,配合另一个选项-input filename使用,可以往filename中写入命令(mplayer -input cmdlist可以显示所有可用命令)以控制MPlayer,达到控制音量、上下切换音频等目的。

安装mplayer很简单,直接apt-get install mplayer即可。
安装后测试使用:mplayer xxx.mp3

不知道怎么的,虽然安装顺利,但是在使用的时候会遇到例如libbcm_host.so文件缺失之类的问题。这个文件在香蕉派中完全查不到任何信息,但是却在树莓派的firmware里面找到了。死马当活马医吧。把缺失的.so文件在respberrypi/firmware/opt/vc/lib/下找到后,下载到香蕉派的/usr/lib目录下。Bingo,最后居然也可用了。

写点代码

配置lircr文件

将/etc/lirc/lircr文件修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# XIXI MODES BEGIN
begin xixi
begin
prog = xixi
button = KEY_PREVIOUS
config = KEY_PREVIOUS
end
begin
prog = xixi
button = KEY_NEXT
config = KEY_NEXT
end
begin
prog = xixi
button = KEY_PLAY
config = KEY_PLAY #这两个配置的意思是,按一次KEY_PLAY会得到KEY_PLAY
config = KEY_PAUSE # 再按一次,会得到KEY_PAUSE,这样轮流取值
end
begin
prog = xixi
button = KEY_VOLUMEDOWN
config = KEY_VOLUMEDOWN
end
begin
prog = xixi
button = KEY_VOLUMEUP
config = KEY_VOLUMEUP
end
begin
prog = xixi
button = KEY_EQUAL
config = KEY_EQUAL
end
begin
prog = xixi
button = KEY_0
config = KEY_0
end
begin
prog = xixi
button = KEY_1
config = KEY_1
end
end xixi

频道0:播放本地音乐

因为我们需要全局控制进行,因此,使用subprocess后,应该还要返回一个子进程对象。

1
2
3
4
5
6
7
8
9
def play_local_music():
'''
local musics in /samba/DLNA/Music/
'''
path = r"/samba/DLNA/Music/*.*" # 本地音乐存储目录
child_process = subprocess.Popen("mplayer -slave -input file=cmd_pannel -shuffle -quiet %s" % path, #若使用列表,会导致没法播放指定目录下的所有文件
shell=True,
)
return child_process, []

频道1:播放悦读FM

同样的,要返回一个子进程对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import os
import json
import random
import subprocess
def play_yuedu_fm():
'''
yuedu.fm
'''
path = r"./yuedu.fm-fetcher/output" # yuedu.fm的音频信息保存目录
items = [item for item in os.listdir(path) if item.startswith("articles")]
item = items[random.randint(0,len(items)-1)] # 随机选择一个articles
articles = json.load(file(os.path.join(path,item)))
play_list = [art["audio"] for art in articles["list"]]
child_process = subprocess.Popen(
["mplayer",'-cache', '1000', '-cache-min', '70','-slave','-input', 'file=cmd_pannel','-quiet'] + play_list]
) # 是滴,这里就是用slave模式
return (child_process, play_list)

其他播放控制

用slave模式打开MPlayer后,我们就可以往控制文件(这里是cmd_pannel)写入命令来控制了播放上/下一首、音量增减、暂停/播放和关闭。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import os
import sys
import lirc

def play_next(): #播放下一首
os.popen("echo 'pt_step 1' > cmd_pannel")
def play_prev(): #播放上一首
os.popen("echo 'pt_step -1' > cmd_pannel")

def play_pause(): #暂停/播放
os.popen("echo 'pause' > cmd_pannel")

def volumn_down(): # 减少音量
os.popen("echo 'volume -10' > cmd_pannel")
def volumn_up(): # 增加音量
os.popen("echo 'volume 10' > cmd_pannel")

def quit(child_process): # 退出Mplayer。这里需要传递一个子进程对象
os.popen("echo 'quit' > cmd_pannel")
child_process.terminate() # 有时候这里的terminate会关不干净
os.system("killall -9 mplayer") # 以防万一
os.popen("echo '' > cmd_pannel") # 以防下次启动MPlayer时里面的值会影响

把它们放在一起

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#-*- coding: utf-8 -*-

def no_operation(*args,**kw): # 默认操作
return 0,[]

if __name__ == "__main__":
channel_map = { # 频道映射
"KEY_0" : play_local_music,
"KEY_1" : play_yuedu_fm,
}
operation_map = { # 命令映射
"KEY_PREVIOUS" : play_prev,
"KEY_NEXT" : play_next,
"KEY_PLAY" : play_pause,
"KEY_PAUSE" : play_pause,
"KEY_VOLUMEDOWN" : volumn_down,
"KEY_VOLUMEUP" : volumn_up,
"KEY_EQUAL" : quit,
}
sockid = lirc.init("xixi")
pid, play_list = None, []
while True: # 不断轮询
rc = lirc.nextcode()
if rc and rc[0] in channel_map: # 若按键是频道按键
if pid: quit(pid) # 若之前有子进程在运行,先把它干掉
pid, play_list = channel_map.get(rc[0],no_operation)()
continue
if "KEY_EQUAL" in rc and pid: # 退出子进程
operation_map.get("KEY_EQUAL",no_operation)(pid)
continue
if rc:
operation_map.get(rc[0], no_operation)()

最后……

  1. 把它放在/etc/rc.local文件中,设置开机自启动,然后想干啥干啥。
  2. 目前我只用了两个频道,要增添频道只要修改lircrc文件,增加频道映射和相应的播放函数即可
  3. ♪(^∇^*)可以回家了~~

参考文档