Shuttersteuerung V1.1
Die Version 1.1 enthält nun auch die Statusabfrage und zeigt an ob der Shutter offen oder geschlossen ist. Dafür nutze ich wieder ein PJLink Kommando. Mit den Kommandos "%1AVMT=30" bzw. "%1AVMT=31" wird der Shutterstatus gesetzt und mit dem Kommando "%1AVMT ?" wird der aktuelle Zustand ausgelesen. Der Beamer antwortet dann mit "%1AVMT=30" bzw. "%1AVMT=31".
Für diese Abfrage gibt es die Funktion "abfrage_shutter()", die auch in einem eigenen Thread läuft. Damit der Beamer nicht mit Abfragen geflutet wird, habe ich nach jeder Abfrage fünf Sekunden Wartezeit eingebaut.
Des Weiteren habe ich noch eine mögliche Fehlerquelle abgefangen, die das Programm zum Absturz gebracht hat. Wenn keine MIDI Schnittstelle vorhanden ist, wird das angzeigt und das Programm kontrolliert beendet.
Um das Programm besser an eine neue Umgebung anpassbar zu machen werden die IP Adresse und der PJLink Port des Beamers in globalen Variablen zu Beginn des Programms definiert.
Für diese Abfrage gibt es die Funktion "abfrage_shutter()", die auch in einem eigenen Thread läuft. Damit der Beamer nicht mit Abfragen geflutet wird, habe ich nach jeder Abfrage fünf Sekunden Wartezeit eingebaut.
Des Weiteren habe ich noch eine mögliche Fehlerquelle abgefangen, die das Programm zum Absturz gebracht hat. Wenn keine MIDI Schnittstelle vorhanden ist, wird das angzeigt und das Programm kontrolliert beendet.
Um das Programm besser an eine neue Umgebung anpassbar zu machen werden die IP Adresse und der PJLink Port des Beamers in globalen Variablen zu Beginn des Programms definiert.
import tkinter as tk
from pygame import midi
import socket
import threading
import sys
from time import sleep
# Globale Variablen
ip = '192.168.20.68'
port = 4352
#PJLink Funktionen
def abfrage_shutter(): #Funktion zur Abfrage des Shuttersstatus
msg = '%1AVMT ?\r' #Zu sendende PJLink Nachricht
msg = msg.encode('UTF-8')
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
data = s.recv(1024)
s.send(msg)
data = s.recv(1024)
if data.decode() == '%1AVMT=30\r': #Wenn Antwort vom Beamer = %1AVMT=30
status = 'Shutter ist offen'
if data.decode() == '%1AVMT=31\r': #Wenn Antwort vom Beamer = %1AVMT=31
status = 'Shutter ist geschlossen'
s.close()
for i in range(5): #5 Sekunden warten und jede Sekunde einen Punkt scheiben
sleep(1)
shutterstatus.set(status + '.'*i)
except:
shutterstatus.set('Fehler! Beamer nicht erreichbar')
def shutter(aktion):
if aktion == 'zu':
msg = '%1AVMT 31\r'
elif aktion == 'auf':
msg = '%1AVMT 30\r'
msg = msg.encode('UTF-8')
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
s.send(msg)
s.close()
#MIDI Funktionen
def midi_decode(key):
#prüfe auf Note on Status, gib Note on Status und Midinote zurück
if key[0] == 144:
s = True
else:
s = False
n = key[1]
return s, n
def midi_eingabe():
#warte auf MIDI Input Signal und löse Shutter Funktion aus
while True:
if midi_input.poll():
eingabe = midi_input.read(num_events=16)
note_on, taste = midi_decode(eingabe[0][0])
if note_on and taste == 125: #F8
shutter('zu')
if note_on and taste == 127: #G8
shutter('auf')
#GUI Funktionen
def callback(event):
#Tastatursteuerung
if event.keysym == 'x':
fenster.destroy()
if event.keysym == 'a':
shutter('auf')
if event.keysym == 'z':
shutter('zu')
def erlaube_tastatur_eingabe():
fenster.bind('<Key>',callback)
#Initialisiere Midi Schnittstelle
try:
midi.init()
default_id = midi.get_default_input_id()
midi_input = midi.Input(device_id=default_id)
except: #Fehlermeldung wenn kein MIDI Interface vohanden ist
b = 300 #Fensterbreite
h = 100 #Fensterhöhe
fehler = tk.Tk()
x = int(fehler.winfo_screenwidth()/2 - b/2) #X-Position für Bilschirmmitte berechnen
y = int(fehler.winfo_screenheight()/2 - h/2) #Y-Position für Bildschirmmitte berechnen
fehler.geometry(f"{b}x{h}+{x}+{y}")
fehler.title("FEHLER")
text = tk.Label(fehler, text="FEHLER: Kein MIDI Interface gefunden")
text.pack()
beenden = tk.Button(text="Beenden", command=fehler.destroy)
beenden.focus()
beenden.pack(pady=20)
fehler.mainloop()
sys.exit()
#Erstelle GUI
fenster = tk.Tk()
fenster.geometry("300x250")
fenster.title("Shuttersteuerung V1.1.0")
text1 = tk.Label(fenster, text="Dieses Tool übersetzt MIDI Noten")
text1.grid(row=1,column=1,columnspan=2)
text2 = tk.Label(fenster, text="in PJLink Kommandos für Panasonic Beamer")
text2.grid(row=2,column=1,columnspan=2)
text3 = tk.Label(fenster, text="Shutter auf:")
text3.grid(row=3,column=1)
text4 = tk.Label(fenster, text="Channel 1, G8")
text4.grid(row=3,column=2)
text5 = tk.Label(fenster, text="Shutter zu:")
text5.grid(row=4,column=1)
text6 = tk.Label(fenster, text="Channel 1, F8")
text6.grid(row=4,column=2)
shutterstatus = tk.StringVar()
shutterstatus.set('Shutter ist...')
text7 = tk.Label(fenster, textvariable=shutterstatus)
text7.grid(row=5, column=1, columnspan=2,pady=10)
button_auf = tk.Button(text="Shutter auf (a)", command=lambda: shutter('auf'))
button_auf.grid(row=6, column=1, pady=10)
button_zu = tk.Button(text="Shutter zu (z)", command=lambda: shutter('zu'))
button_zu.grid(row=6, column=2, pady=10)
button_quit = tk.Button(text="Beenden (x)", command=fenster.destroy)
button_quit.focus()
button_quit.grid(row=7,column=2, pady=10)
erlaube_tastatur_eingabe()
#Öffne neuen Thread für Midi Input Loop
t1 = threading.Thread(target=midi_eingabe)
t1.daemon = True
t1.start()
#Öffne neuen Thread für Statusabfrage des Shutters
t2 = threading.Thread(target=abfrage_shutter)
t2.daemon = True
t2.start()
#Starte GUI
fenster.mainloop()
#Stoppe alle Threads
sys.exit()