I'm a bit new to Python and I'm developping an application for a Raspberry Pi where a motion sensor is connected.
The idea is to place this Raspberry in a room and on motion detection a video starts playing fullscreen.
After the video is done playing I want to let the device sleep for 10 minutes and than activate the motion sensor again to play the same video again. The screen also should stay black after the video so not quiting the vlc application and see the Raspberry Pi Desktop.
So far I tried some code where in one file the fullscreen works, and in the other file the loop works, but bringing the 2 files togheter is giving errors.
As I said I'm very new to coding so it could be the problem is very stupid and the solution very simple. Thanks in advance for the help.
Down below my 2 code-files.
Option 1 (fullscreen not working)
from gpiozero import MotionSensor, LED
from time import sleep
import vlc
# creating Instance class object
player = vlc.Instance()
# creating a new media list
media_list = player.media_list_new()
# creating a media player object
media_player = player.media_list_player_new()
# creating a new media
media = player.media_new("/home/pi/MOSA25.mp4")
# adding media to media list
media_list.add_media(media)
# setting media list to the mediaplayer
media_player.set_media_list(media_list)
# setting loop
player.vlm_set_loop("1", True)
#fullscreen
#media_player.set_fullscreen(True)
#Motion Sensor
pir = MotionSensor(4)
#Led
led = LED(26)
led.off()
print("Sensor loading.")
pir.wait_for_no_motion()
sleep(5)
while True:
print("Ready")
pir.wait_for_motion()
print("Motion detected")
led.on()
sleep(5)
led.off()
media_player.play()
sleep(30)
OPTION 2 (Loop not working)
from gpiozero import MotionSensor, LED
from time import sleep
import vlc
# creating Instance class object
vlc_instance = vlc.Instance()
player = vlc_instance.media_player_new()
player.set_mrl("/home/pi/MOSA25.mp4")
player.set_fullscreen(True)
# setting loop
#player.vlm_set_loop("1", True)
#Motion Sensor
pir = MotionSensor(4)
#Led
led = LED(26)
led.off()
print("Sensor wordt geladen.")
pir.wait_for_no_motion()
sleep(5)
while True:
print("Ready")
pir.wait_for_motion()
print("Motion detected")
led.on()
sleep(5)
led.off()
player.play()
sleep(20)
Keep track of the video playing in another while loop and reload before starting again.
Here's your code (adjusted as I don't have your kit)
from time import sleep
import vlc
playing = set([1,2,3,4])
# creating Instance class object
vlc_instance = vlc.Instance()
player = vlc_instance.media_player_new()
player.set_fullscreen(True)
#Motion Sensor
#pir = MotionSensor(4)
#Led
#led = LED(26)
#led.off()
print("Sensor wordt geladen.")
#pir.wait_for_no_motion()
sleep(5)
while True:
print("Ready")
# pir.wait_for_motion()
sleep(1)
print("Motion detected")
# led.on()
sleep(1)
# led.off()
player.set_mrl("/home/pi/MOSA25.mp4")
player.play()
sleep(1)
while player.get_state() in playing:
sleep(1)
continue
print("Finished")
sleep(5)
continue
Related
I am looking to iterate through a list of songs such as Songs = ["Song1.mp3", "Song2.mp3", "Song3.mp3"] and I want to play each song one after each other.
I have tried various methods, the most suggested seemed to use pygame, however, I have not been able to debug the tremendous amount of errors that come with using it. My main source code and attempt at this is as shown below:
from tkinter import *
import pygame
from random import choice
import os
pygame.mixer.init()
Songs = os.listdir("Music\\")
def Play():
Song = choice(Songs)
pygame.mixer.music.load("Music\\" + Song)
pygame.mixer.music.play()
while True:
play()
Upon running this I receive error pygame.error: ModPlug_Load failed.
I am running this concurrently inside of a slideshow program I have, I want this code to run as background music and I plan on checking for the end of the song in a Function I already have set.
Use pygame.mixer.music.get_busy() to detect if a music stream is actively playing. Play the next song from the list when no stream is active. e.g:
import pygame
play_list = ["song1.mp3", "song2.mp3", "song3.mp3"]
current_list = []
pygame.init()
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if not pygame.mixer.music.get_busy():
if not current_list:
current_list = play_list[:]
current_song = current_list.pop(0)
pygame.mixer.music.load(current_song)
pygame.mixer.music.play()
pygame.quit()
exit()
You can register a custom event which will be triggered when the music is done playing using pygame.mixer.music.set_endevent().
Also you need to run the while loop in a child thread if you want to run concurrently with main application.
Below is an example:
import os
import random
import threading
import tkinter as tk
import pygame
pygame.init()
# create a custom event
MUSIC_DONE = pygame.event.custom_type()
# register the event
pygame.mixer.music.set_endevent(MUSIC_DONE)
folder = "Music\\"
Songs = os.listdir(folder)
def next_song():
try:
song = random.choice(Songs)
pygame.mixer.music.load(os.path.join(folder, song))
pygame.mixer.music.play()
# update song name
song_var.set(song)
except Exception as e:
print(e)
def pygame_loop():
next_song()
while pygame.get_init():
for event in pygame.event.get():
if event.type == MUSIC_DONE:
# current song done playing, play next song
next_song()
root = tk.Tk()
# label to show the current song being played
song_var = tk.StringVar()
tk.Label(root, textvariable=song_var).pack()
# start the pygame loop in a child thread
threading.Thread(target=pygame_loop).start()
root.mainloop()
# quit pygame
pygame.quit()
If it's a desktop app, you have multiple options to play a file, usually, it depends:
Also to avoid Tkinter being stuck, you need to use threads or multiprocess. I recommend you soundfile player, you will find examples here https://realpython.com/playing-and-recording-sound-python/
I am looking to iterate through a list of songs such as Songs = ["Song1.mp3", "Song2.mp3", "Song3.mp3"] and I want to play each song one after each other.
I have tried various methods, the most suggested seemed to use pygame, however, I have not been able to debug the tremendous amount of errors that come with using it. My main source code and attempt at this is as shown below:
from tkinter import *
import pygame
from random import choice
import os
pygame.mixer.init()
Songs = os.listdir("Music\\")
def Play():
Song = choice(Songs)
pygame.mixer.music.load("Music\\" + Song)
pygame.mixer.music.play()
while True:
play()
Upon running this I receive error pygame.error: ModPlug_Load failed.
I am running this concurrently inside of a slideshow program I have, I want this code to run as background music and I plan on checking for the end of the song in a Function I already have set.
Use pygame.mixer.music.get_busy() to detect if a music stream is actively playing. Play the next song from the list when no stream is active. e.g:
import pygame
play_list = ["song1.mp3", "song2.mp3", "song3.mp3"]
current_list = []
pygame.init()
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if not pygame.mixer.music.get_busy():
if not current_list:
current_list = play_list[:]
current_song = current_list.pop(0)
pygame.mixer.music.load(current_song)
pygame.mixer.music.play()
pygame.quit()
exit()
You can register a custom event which will be triggered when the music is done playing using pygame.mixer.music.set_endevent().
Also you need to run the while loop in a child thread if you want to run concurrently with main application.
Below is an example:
import os
import random
import threading
import tkinter as tk
import pygame
pygame.init()
# create a custom event
MUSIC_DONE = pygame.event.custom_type()
# register the event
pygame.mixer.music.set_endevent(MUSIC_DONE)
folder = "Music\\"
Songs = os.listdir(folder)
def next_song():
try:
song = random.choice(Songs)
pygame.mixer.music.load(os.path.join(folder, song))
pygame.mixer.music.play()
# update song name
song_var.set(song)
except Exception as e:
print(e)
def pygame_loop():
next_song()
while pygame.get_init():
for event in pygame.event.get():
if event.type == MUSIC_DONE:
# current song done playing, play next song
next_song()
root = tk.Tk()
# label to show the current song being played
song_var = tk.StringVar()
tk.Label(root, textvariable=song_var).pack()
# start the pygame loop in a child thread
threading.Thread(target=pygame_loop).start()
root.mainloop()
# quit pygame
pygame.quit()
If it's a desktop app, you have multiple options to play a file, usually, it depends:
Also to avoid Tkinter being stuck, you need to use threads or multiprocess. I recommend you soundfile player, you will find examples here https://realpython.com/playing-and-recording-sound-python/
I try to develop some code on a machine without GPIO. As GPIO library I selected a gpiozero to be able to write my code without access to gpio of raspberry pi.
My problem, I cant get ride of .when_pressed event in the code.
I simulate state change of the button, but the function is not called.
Device.pin_factory = MockFactory()
def interrupt_Event(channel):
print("%s puted in the queue", channel)
InputPin.Device.pin_factory.pin(channel)
InputPin.when_pressed = interrupt_Event
def main():
try:
while True:
time.sleep(1)
InputPins[channel].pull=drive_high()
time.sleep(0.1)
print("State CHANNEL %s" % channel)
print(InputPins[channel].state)
InputPins[channel].drive_low()
Till now I have no Idea what is wrong.
when_pressed function should not have arguments (see 2.7 in https://gpiozero.readthedocs.io/en/stable/recipes.html).
You could define the callback using a loop :Creating functions in a loop
(use channel=channel to force early binding of channel value as in example below)
for channel in channels:
def onpress(channel=channel):
print("%s puted in the queue", channel)
InputPins[channel].when_pressed = onpress
I am not convinced that you are using drive_high and drive_low to simulate the button pushing.
I have a almost identical problem. using Mock pins to develop a Pi program on windows, I find that the callback routines are not called.
from gpiozero.pins.mock import MockFactory
from gpiozero import Device, Button, LED
from time import sleep
Device.pin_factory = MockFactory() # set default pin
factory
btn = Button(16)
# Get a reference to mock pin 16 (used by the button)
btn_pin = Device.pin_factory.pin(16)
def pressed(): # callback
print('pressed')
def released(): # callback
print('released')
btn.when_pressed = pressed
btn.when_released = released # callback routine
for i in range(3): # now try to signal sensor
print('pushing the button')
btn_pin.drive_high
sleep(0.1)
btn_pin.drive_low
sleep(0.2)
The output has no callbacks, just
pushing the button
pushing the button
pushing the button
>>>
I am trying to create a media player with Python that will play mp3 files one after the other and allow me to play and pause the music at any time (similar to spotify).
I have used the vlc library and pygame music function to play the files, but my problem comes when the song has finished and I want it to play the next file. I have manged to do this but not with a play and pause functionality.
My rough code:
import pygame
import time
#plays first mp3 file
file = '4c68Z9wLdHc36y3CNjwQKM.ogg'
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load(file)
pygame.mixer.music.play()
#play and pause funtionnality
while pygame.mixer.music.get_busy():
timer = pygame.mixer.music.get_pos()
time.sleep(1)
control = input()
pygame.time.Clock().tick(10)
if control == "pause":
pygame.mixer.music.pause()
elif control == "play" :
pygame.mixer.music.unpause()
elif control == "time":
timer = pygame.mixer.music.get_pos()
timer = timer/1000
print (str(timer))
elif int(timer) > 10:
print ("True")
pygame.mixer.music.stop()
break
else:
pass
#next mp3 file
file = '3qiyyUfYe7CRYLucrPmulD.ogg'
pygame.mixer.music.load(file)
pygame.mixer.music.play()
When I run this my hope is that it will play the first file and allow me to play and pause, but it stops when a song ends and not play the next one, as it gets stuck waiting for an input.
I want it to play the first file, allowing me to pause and resume it at any time, and then when the song has finished, it automatically plays the next file.
Thanks in advance.
To narrow it down I would like to know how to create a while that has a user input that will always check for a condition and not just at the start of the while loop.
I'm not sure why you tagged this question vlc if you are using pygame as arguably vlc.py has this functionallity pretty much built in.
However, all you need to do is use a double while statement.
The first controls the file to be played and the second performs your play/pause control. e.g.
import pygame
import time
files = ['./vp1.mp3','./vp.mp3']
pygame.init()
pygame.mixer.init()
stepper = 0
#file loading
while stepper < len(files):
pygame.mixer.music.load(files[stepper])
print("Playing:",files[stepper])
stepper += 1
pygame.mixer.music.play()
#play and pause
while pygame.mixer.music.get_busy():
timer = pygame.mixer.music.get_pos()
time.sleep(1)
control = input()
pygame.time.Clock().tick(10)
if control == "pause":
pygame.mixer.music.pause()
elif control == "play" :
pygame.mixer.music.unpause()
elif control == "time":
timer = pygame.mixer.music.get_pos()
timer = timer/1000
print (str(timer))
elif int(timer) > 10:
print ("True")
pygame.mixer.music.stop()
break
else:
continue
this will be my first post here, hope it will go well!
I am new to both Raspberry Pi3 and Python, but I wanted to give it a try. I have connected my Pi to a button, and when I push it, I want to play a sound. When I run my code, everything looks ok, and when I push the button, VLC plays the wav-file. All good. But... VLC will only play the wav-file once, when I press the button again, only the "Now func1 is done" appears on the screen, but no more sound:(
I need to close and re-run my program to be able to hear the wav again, and only once. How do I get my program to run the wav everytime I push my button without restarting?
Thx!
import RPi.GPIO as GPIO
from time import sleep
import vlc
GPIO.setmode(GPIO.BOARD)
player = vlc.MediaPlayer("/home/pi/Desktop/ljud/aliengun.wav")
stime = 1
button = 11
GPIO.setup(button, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def func1():
player.play()
print("Now func1 is done")
try:
while True:
input_state = GPIO.input(button)
if input_state != 1:
func1()
sleep(stime)
finally:
GPIO.cleanup()