0

I'm writing a Jukebox program that plays media based on key combinations (A1, B2, C3, etc.). Everything works the way I expect with the exception of the "media_player.next()" command.

Let's say you queue up 3 songs. If you hit the "y" key, it skips the song as I'd expect. My issue is that once it gets to the 3rd song, if you hit "y" again, it will circle back to the first song. I don't want that. I want the "y" key to take you forward in the media list...if that is the last song in the media list, don't go to the next song. How do I know if that's the last song in the media list or how do you stop VLC from going back to the beginning?

#!/usr/bin/env python3
#
import os, sys, csv, vlc, time, serial
from pynput.keyboard import Key, Listener
#
# Set Defaults
#
DefaultUSBPath="/media/pi"
#
# Declare variables
#
USBDrive = None
Action = None
Playlist = []
SelectionCount = []
Sel_char = None
#
# Find the USB Drive
#
USBDrive =  os.path.join(DefaultUSBPath, "USB30FD")
#
# 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 None:
        print ("Error(4) - Selection has no media")
    return list
#
# MediaPlayer function
#
def vlc_WhatsPlaying():
    pass
def vlc_SongStarted(event):
    print("Started")
    song = media_player.get_media_player().get_media().get_mrl() # return path of current playing media
    print(song)
    splittrack = song.split("/")
    track = splittrack[-2]
    print(track)
    return
    
def vlc_SongFinished(event):
    print("Finished")
    song = media_player.get_media_player().get_media().get_mrl() # return path of current playing media
    print(song)
    splittrack = song.split("/")
    track = splittrack[-2]
    #media_list.remove_index(0)
    #media_player.play_item_at_index(1)
    return
#
# Define keyboard actions
#
def on_press(key):
    global Action, 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:
        Plist = None
        Action = Action + str(Sel_char)
        print("Action: " + Action)
        Plist = addplaylist(Action)
        if Plist is not None:
            if ";" in Plist:
                print(Plist)
                Plist = Plist.split(";")
                for p in Plist:
                    media_list.add_media(p)
            else:
                media_list.add_media(Plist)
            # find section in array and increase the count by one
            if not media_player.is_playing():
                media_player.play()
        else:
            print ("Error(4) - Selection has no media")
    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
media_player = vlc.MediaListPlayer()  # creating a media player object
media_list = player.media_list_new()  # creating a new media list
media_player.set_media_list(media_list)  # setting media list to the media player
new = player.media_player_new()  # new media player instance
media_player.set_media_player(new)  # setting media player to it
media_events = new.event_manager()  # setting event handler
# setting up events
media_events.event_attach(vlc.EventType.MediaPlayerMediaChanged, vlc_SongStarted)
media_events.event_attach(vlc.EventType.MediaPlayerEndReached, vlc_SongFinished)

# Read keyboard input
#
print("Ready...")
with Listener(on_press=on_press) as listener:
    listener.join()
#
# Program is shutting down
#

print ("")
print ("Have a nice day!")
print ("")
sys.exit()
Brian
  • 93
  • 1
  • 11
  • 1
    There's the `MediaListEndReached` event that you may be able to utilise or simply track the index of the played items against the length of the list, then bail-out when you reach the end. – Rolf of Saxony Mar 14 '21 at 14:45
  • I couldn't get the MediaListEndReached event to fire, but according to my "Google-foo", I might not be the only person with that issue. I tracked manually and just don't allow the "next()" function to be called if I don't think there's anymore music in the queue. Thanks for the help. – Brian Mar 15 '21 at 20:47

1 Answers1

0

As mentioned in my comment the MediaListEndReached doesn't appear to do anything for me, so running with the idea of the list being the easiest way of addressing the issue, the following code tests the list position of the item being played and exits, if the next or previous command attempts to pass beyond the end of the list.
You can achieve the same result simply tracking an index variable.
You may have to adjust the splitting of the mrl to match the entries in your list.

import vlc
import time

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

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

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)    
    m = player.get_media_player()
    print("Playing - ",m.get_media().get_mrl()) 
    while True:
        k = getch()

        if k == "n": #Next
            media = m.get_media()
            if media.get_mrl().rsplit("/",1)[1] == mymedia[-1]: #Next requested but already at the end
                break 
            player.next()
        if k == "p": #Previous
            media = m.get_media()
            if media.get_mrl().rsplit("/",1)[1] == mymedia[0]: #Previous requested but already at the beginning
                break 
            player.previous()
        if k == " ": #Pause
            player.pause()
        if k == "q": #Quit
            player.stop()
            return True
        time.sleep(0.1)
        state = player.get_state()
        print(state,m.get_media().get_mrl()) 

    print("End of list")

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()
Rolf of Saxony
  • 21,661
  • 5
  • 39
  • 60