我正在开发一个程序来替换旧 Wurlitzer 点唱机的所有内容。我将有 3 个设备,一个 Ipac(用于将选择按钮转换为按键),一个 Arduino Mega(用于控制“正在播放的灯”和 2 个其他继电器)和一个 Raspberry Pi 4(它将让我的 python 程序无头运行)。
我终于想出了如何在 Python 中更好地使用 VLC,并且在这个网站的帮助下,我的媒体列表工作了,“下一步”按钮现在工作了。
这是我的代码:
#!/usr/bin/env python3
#
import os, sys, csv, vlc, time, serial
from pynput.keyboard import Key, Listener
DefaultUSBPath="/media/pi"
PlayHistory="PlayHistory.csv"
#
# Declare variables
#
USBDrive = None
Action = None
Playlist = []
SelectionCount = []
Sel_char = None
#
# Find the USB Drive
#
for item in os.listdir(DefaultUSBPath):
if os.path.isdir(os.path.join(DefaultUSBPath, item)):
if USBDrive is None:
USBDrive = os.path.join(DefaultUSBPath, item)
else:
USBDrive = USBDrive + ";" + os.path.join(DefaultUSBPath, item)
if USBDrive is None:
print ("Error(0) - No USB Drive detected")
sys.exit()
elif ";" in USBDrive:
print ("Error(1) - More than one USB Drive detected.")
sys.exit()
#
# Create/Find/Open PlayHistory.csv
# Create media folders as needed if new PlayHistory file is created
#
if os.path.isfile(os.path.join(USBDrive, PlayHistory)):
datafile = open(os.path.join(USBDrive, PlayHistory), 'r+')
datareader = csv.reader(datafile, delimiter=',')
for row in datareader:
SelectionCount.append(row)
else:
datafile = open(os.path.join(USBDrive, PlayHistory), 'w+')
datawriter = csv.writer(datafile, delimiter=',')
datawriter.writerow(['Selection', 'Count'])
SelectionCount.append(['Selection', 'Count'])
for x in range (65, 87):
if x == 73 or x == 79:
continue
for y in range (1,11):
if y == 10:
datawriter.writerow([chr(x) + str(0),0])
SelectionCount.append([chr(x) + str(0),0])
# if not os.path.isdir(os.path.join(USBDrive, chr(x) + str(0))):
# os.makedirs(os.path.join(USBDrive, chr(x) + str(0)))
else:
datawriter.writerow([chr(x) + str(y),0])
SelectionCount.append([chr(x) + str(y),0])
# if not os.path.isdir(os.path.join(USBDrive, chr(x) + str(y))):
# os.makedirs(os.path.join(USBDrive, chr(x) + str(y)))
datafile.flush()
datafile.close()
#
# Establish Serial communications to Arduino
#
Arduino = None
try:
ser=serial.Serial('/dev/ttyACM0', 9600, timeout=1)
ser.flush()
Arduino = True
except:
print ("Error(2) - Arduino not found. Lights/Relays will not function.")
Arduino = False
#
# Adding to playlist - Returns directory contents and adds to playlist
#
def addplaylist(track):
list = None
if os.path.isdir(os.path.join(USBDrive, track)):
files = [f for f in os.listdir(os.path.join(USBDrive, track)) if os.path.isfile(os.path.join(USBDrive, track, f))]
for f in files:
if list is None:
list = os.path.join(USBDrive, track, f)
else:
list = list + ";" + os.path.join(USBDrive, track, f)
else:
print ("Error(3) - Selection is invalid")
if list is not None:
if ";" in list:
list = list.split(";")
else:
print ("Error(4) - Selection has no media")
return list
#
# Find location of Selection in SelectionCount 2D array
#
def find(l, elem):
for row, i in enumerate(l):
try:
column = i.index(elem)
except ValueError:
continue
return row, column
return -1
#
# MediaPlayer function
#
def MusicPlayer(P):
global Playlist, player
media_list.add_media(Playlist)
#media_player.play()
#while len(Playlist) > 0:
# song=Playlist.pop(0)
# print("Song: ")
# print(song)
# splittrack = song.split("/")
# track = splittrack[-2]
# print (track)
# if Arduino:
# ser.write(track.encode())
# player=vlc.MediaPlayer(song)
# player.play()
#
# Define keyboard actions
#
def on_press(key):
global Action, Playlist, player
try:
Sel_char = int(key.char)
except:
try:
Sel_char = str(key.char)
Sel_char = Sel_char.upper()
except:
Sel_char = None
if Sel_char == "Z":
return False
elif Sel_char == "Y":
print("Skip")
media_player.next()
elif type(Sel_char) == str:
Action = Sel_char
elif type(Sel_char) == int:
Action = Action + str(Sel_char)
print("Action: " + Action)
Plist = addplaylist(Action)
if Plist is not None:
print("Added to playlist")
Playlist.append(Plist)
print(Plist)
# find section in array and increase the count by one
count1,count2=find(SelectionCount, Action)
SelectionCount[count1][1] = int(SelectionCount[count1][1]) + 1
media_list.add_media(Plist)
if not media_player.is_playing():
media_player.play()
else:
pass
#
# Setting Up Media Player
#
# creating Instance class object
player = vlc.Instance('--no-xlib --quiet ') # no-xlib for linux and quiet don't complain
# creating a media player object
media_player = vlc.MediaListPlayer()
# creating a new media list
media_list = player.media_list_new()
# setting media list to the media player
media_player.set_media_list(media_list)
# new media player instance
new = player.media_player_new()
# setting media player to it
media_player.set_media_player(new)
#
# Read keyboard input
#
with Listener(on_press=on_press) as listener:
listener.join()
#
# Program is shutting down
#
if Arduino:
ser.write(b"I0\n")
print ("")
print ("Writing Play Counts to PlayHistory file")
datafile = open(os.path.join(USBDrive, PlayHistory), 'w+')
datawriter = csv.writer(datafile, delimiter=',')
datawriter.writerows(SelectionCount)
datafile.flush()
datafile.close()
print ("")
print ("Have a nice day!")
print ("")
sys.exit()
我的第一个挑战是“下一步”按钮。如果我在播放列表中放 3 多首歌曲,在播放第一首歌曲并开始播放第二首歌曲后,我点击跳过(在本例中为“Y”)按钮并从第二首曲目转到第三首曲目。好的酷。但如果我再次点击“下一个”,它会回到第一首曲目。我该如何阻止这个?播放完一首歌后,我希望 VLC 忘记它,或者至少不要在点击“下一个”时返回。
我的第二个挑战,坦率地说是更重要的一个......我需要知道 VLC 何时开始播放列表中的下一首歌曲。你可以看到“def MusicPlayer”……这曾经是我在 VLC 播放时试图控制每首歌曲的时候。它不能正常工作,这就是它被评论的原因,但它显示了我需要对以下几行做些什么:
# splittrack = song.split("/")
# track = splittrack[-2]
# print (track)
# if Arduino:
# ser.write(track.encode())
我需要获取正在播放的内容的完整路径,因此我可以将其拆分并获取目录继续实际文件名。这将是已输入的选择(A1、B2 等)。我需要将其发送到 Arduino 设备,以便在播放该曲目时自动点唱机上的“正在播放”灯正确亮起。我还需要知道 vlc 播放器是否停止(播放列表中的歌曲用完),因为我需要向 Arduino 发送一个“关闭”代码,这样它就知道不会点亮任何东西。
任何帮助将不胜感激。
谢谢。布赖恩