Я пишу программу на Python для работы на Raspberry Pi, чтобы управлять своим музыкальным автоматом Wurlitzer. Программа current принимает коды для «выбора записи» (A1, B1, C4 и т. Д.), Добавляет эти коды в список воспроизведения и выполняет список. Моя проблема в том, что как только песня начинается, я хотел бы иметь возможность нажать кнопку («Y» в текущем коде), чтобы пропустить текущую песню. Я не могу заставить это работать.

Если я использую player.next (), я получаю сообщение об ошибке: объект MediaPlayer не имеет атрибута next.

Я попытался остановить проигрыватель и перезапустить его (думая, что он выберет следующую песню в плейлисте. Это даже не останавливает проигрыватель.

Я не хочу использовать подпроцесс, если могу этого избежать. Я хотел бы найти способ в Python сделать пропуск. Как этого добиться?

import os, sys, csv, vlc, time, threading
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()
#
# 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(2) - Selection is invalid")
    if list is not None:
        if ";" in list:
            list = list.split(";")
    else:
        print ("Error(3) - Selection has no media")
    return list
#
# MediaPlayer function
#
def MusicPlayer(P):
    global Playlist, player
    while len(Playlist) > 0:
        song=Playlist.pop(0)
        print("Song: ")
        print(song)
        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")
        #player.next()     This line causes 'MediaPlayer' object has no attribute 'next'
        time.sleep(1)
        MusicPlayer(Playlist)
    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)
            MusicPlayer(Playlist)
    else:
        pass
#
# Read keyboard input
#
with Listener(on_press=on_press) as listener:
    listener.join()
print ("")
print ("Have a nice day!")
print ("")
sys.exit()
1
Brian 23 Фев 2021 в 18:03

1 ответ

Лучший ответ

Как вы его закодировали, я ожидаю, что вам придется остановить его, удалить текущий носитель из списка, а затем перезапустить его.

Однако вам может быть лучше работать с media_list_player, см. Ниже скелетную версию. Обратите внимание: я использую Linux, и мне пришлось взломать некоторый код, чтобы получить ключевой ввод, вместо того, чтобы использовать определенную библиотеку или тратить на нее время, но это должно дать вам достаточно для работы.

редактировать

Прошу прощения, есть гораздо более простой способ использования media_list_player, хотя, если вам нужен более точный контроль, вы должны использовать media_list_player, где вы управляете индексом списка, или для полного контроля используйте media_player_new() но это выходит за рамки этого вопроса. (Я оставлю исходный ответ под этим кодом, так как он может быть полезен)

import vlc
import time

## pinched from vlc for keyboard input
import termios
import tty
import sys

mymedia = ["vp.mp3","vp1.mp3","happy.mp3","V1.mp4"]

def getch():  # getchar(), getc(stdin)  #PYCHOK flake
    fd = sys.stdin.fileno()
    old = termios.tcgetattr(fd)
    try:
        tty.setraw(fd)
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old)
    return ch
## end pinched code

def jukebox():
    player.play_item_at_index(0)    
    while True:
        time.sleep(0.25)
        k = getch()
        if k == "n": #Next
            player.next()
        if k == "p": #Previous
            player.previous()
        if k == " ": #Pause
            player.pause()
        if k == "q": #Quit
            player.stop()
            return True

    player.next()
            
vlc_instance = vlc.Instance('--no-xlib --quiet ') # no-xlib for linux and quiet don't complain
player = vlc_instance.media_list_player_new()
Media = vlc_instance.media_list_new(mymedia)
player.set_media_list(Media)

print("Welcome to Jukebox")
print("Options - space = Play/Pause, n = Next, p = Previous, q = Quit")
print("Media",mymedia)

jukebox()

Исходный код

import vlc
import time

## pinched from vlc for keyboard input
import termios
import tty
import sys

def getch():  # getchar(), getc(stdin)  #PYCHOK flake
    fd = sys.stdin.fileno()
    old = termios.tcgetattr(fd)
    try:
        tty.setraw(fd)
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old)
    return ch
## end pinched code


vlc_instance = vlc.Instance()
player = vlc_instance.media_list_player_new()
mymedia = ["vp.mp3","vp1.mp3","happy.mp3"]
Media = vlc_instance.media_list_new(mymedia)
player.set_media_list(Media)
for index, name in enumerate(mymedia):
    print("Playing:",name)
    player.play_item_at_index(index)    
    time.sleep(1)
    while player.get_state() != 6:
        time.sleep(1)
        k = getch()
        if k == "y":
            player.stop()
            break
1
Rolf of Saxony 24 Фев 2021 в 10:19