ich hab leider nicht geschafft, eine funktionierende Socket-Verbindung mit den C-Befehlen zu bauen. Irgendwann hab ich mal den KI-Chat von Ecosia gefragt, aber dann wurde alles sehr (für mich) kompliziert und hat trotzdem nicht funktioniert. Eigentlich das gleiche Ergebnis, welches ich zuvor erreicht habe.
Jetzt hab ich mich für die Verwendung von socat entschieden. Mußte mich da auch reinwühlen, aber läuft
Hier mal ein lauffähiger Test/Demo Code - vllt. etwas zu ausführlich kommentiert, aber kann man ja entfernen. Ich brauch das, damit ich später noch durchsehe
Code: Alles auswählen
;- top --
; Beispiel: Steuerung von mpv über TCP-IPC mit PureBasic 6.21 // Zum Testen mpv im Terminal starten:
; mpv --input-ipc-server=/tmp/mpvsocket /pfad/zum/audioverzeichnis/ //mpvsocket ist ein variabeler Name, darf pro Instanz nur 1x vorkommen //einach name ändern
; socat muß installiert sein. Check im Terminal mit 'which socat'. Sonst 'sudo apt install socat'.
; socat starten: socat TCP-LISTEN:50101,reuseaddr, UNIX-CONNECT:/tmp/mpvsocket //die Port-Nr. darf pro Instanz nur 1x vorkommen //einfach hochzählen
; listen: Wird bei TCP-Lauschen verwendet, um den Socket in den Lausch-Modus zu versetzen.
; reuseaddr: Erlaubt das sofortige Wiederverwenden einer lokalen Adresse (Port), auch wenn sie noch in TIME_WAIT ist.
; fork: Erlaubt mehrere gleichzeitige Verbindungen, indem für jede Verbindung ein neuer Prozess gestartet wird.
; habe fork weggelassen, weil sich socat dann automatisch beendet, wenn die Verbindung wieder geschlossen wird //mit fork bleibt socat aktiv
; falls jedoch weitere Pcs im Netzwerk auf den gleichen mpv-Socket zugreifen wollen, muß fork gesetzt werden und am Zielsystem manuell beendet werden
; wenn mpv läuft, startet dieses Programm socat und erstellt eine TCP-Verbindung mit den mpv-socket
; ich sende JSON-Befehle zum Pausieren und Fortsetzen der Wiedergabe und zum Beenden.
;Dynamische/Private Ports 49152 – 65535 Für private oder temporäre Zwecke vorgesehen.
; ---------------------------------------------------------
Define.s mpvpfd = "/tmp/mpvsocket"
Define.i mpvport = 50101, so_ID, sid
Procedure.i mpv_socat(port.i,pfd.s)
;socat TCP-LISTEN:50100,reuseaddr, UNIX-CONNECT:/tmp/mpvsocket //beide adressen müssen mit einem Leerzeichen getrennt sein // die argumente für eine adresse mit komma OHNE leerzeichen
;Dies muß nur auf dem pc gemacht werden, auf dem mpv mit der option --input-ipc-server=/tmp/mpvsocket gestartet wurde
;// bei fernsteuerung vom anderen pc muß nur tcp zur ip des mpv-pc verbunden werden und auf dem mpv-pc socat mit der zusätzlichen option fork gestartet werden
;Param: tcp-port // mpv-socket-pfad
ProcedureReturn RunProgram("socat","TCP-LISTEN:" + port + "," + "reuseaddr" + ", " + "UNIX-CONNECT:" + pfd,"") ;alle argumente einzeln, falls ich einige Parameter ändern möchte
EndProcedure
Procedure.i mpv_socket(status.i,port_soid.i,ip.s="127.0.0.1")
;verbindet oder trennt mpv-socket-verbindungen
;param: status:1=verbinden 0=trennen// port_soid: port-nr, wenn verbunden werden soll, Socket-ID, wenn getrennt werden soll// ip: IPadresse 127.0.0.1 für local
; ;beim beenden (status=0) kann die IP beim Aufruf weggelassen werden. Wird sie auch beim verbinden (status=1) weggelassen, wird local 127.0.0.1 verwendet
Select status ;verbindeen oder trennen?
Case 1 ;verbinden
ProcedureReturn OpenNetworkConnection(ip, port_soid, #PB_Network_TCP)
Case 0 ;trennen
If IsProgram(sid) ;wenn socat noch läuft
CloseNetworkConnection(port_soid)
EndIf
ProcedureReturn 0 ;beim beende wird immer 0 zurückgegeben, weil dies auch nicht ausgewertet wird
EndSelect
;Rückgabe: bei erfolg die socketID oder: 0, bei verbindungs-fehler und beim beenden
EndProcedure
Procedure mpv_command(soid.i,funkt.i)
;sendet das json kommando an mpv-socket// param: soid: socked-ID// funkt: 1=pause, 0=play
Protected result.i
Select funkt ;was soll mpv machen?
Case 1 ;pause
result = SendNetworkString(soid, "{" + #DQUOTE$ + "command" + #DQUOTE$ + ": [" + #DQUOTE$ + "set_property" + #DQUOTE$ + ", " + #DQUOTE$ + "pause" + #DQUOTE$ + ", true]}" + Chr(10))
If result ;wenn gesendet
SetGadgetText(1,"Play") ;toggelbutton neu beschriften
Else
SetGadgetText(1,"???") ;sonst mitteilen
EndIf
Case 0 ;play
result = SendNetworkString(soid, "{" + #DQUOTE$ + "command" + #DQUOTE$ + ": [" + #DQUOTE$ + "set_property" + #DQUOTE$ + ", " + #DQUOTE$ + "pause" + #DQUOTE$ + ", false]}" + Chr(10))
If result ;wenn gesendet
SetGadgetText(1,"Pause") ;toggelbutton neu beschriften
Else
SetGadgetText(1,"???") ;sonst mitteilen
EndIf
Case 2 ;beenden
result = SendNetworkString(soid, "{" + #DQUOTE$ + "command" + #DQUOTE$ + ": [" + #DQUOTE$ + "quit" + #DQUOTE$ + "]}" + Chr(10))
If result ;wenn gesendet
SetGadgetText(1,"???") ;mitteilen
DisableGadget(1, #True); pause/play deaktivieren
DisableGadget(2, #True); Ende deaktivieren
EndIf
EndSelect
;weitere Kommandos sind möglich:
;ein titel zurück:
;result = SendNetworkString(soid, "{" + #DQUOTE$ + "command" + #DQUOTE$ + ": [" + #DQUOTE$ + "playlist_prev" + #DQUOTE$ + "]}" + Chr(10))
;ein titel vor:
;result = SendNetworkString(soid, "{" + #DQUOTE$ + "command" + #DQUOTE$ + ": [" + #DQUOTE$ + "playlist_next" + #DQUOTE$ + "]}" + Chr(10))
EndProcedure
Procedure fensterelemente()
;fenster und bedienelemente bauen
OpenWindow(0, 50, #PB_Ignore, 150, 40, "mpvR",#PB_Window_Tool)
StickyWindow(0,#True) ;fenster fest im vordergrund
ButtonGadget(1, 0, 5, 45, 25, "Pause",#PB_Button_Toggle)
ButtonGadget(2, 47, 5, 45, 25, "Ende")
ButtonGadget(3, 94, 5, 45, 25, "---",#PB_Button_Toggle)
DisableGadget(1, #True) ; pause/play erstmal deaktivieren, bis ich die socketverbindung hergestellt habe
DisableGadget(2, #True) ; -"-
EndProcedure
fensterelemente()
sid = mpv_socat(mpvport,mpvpfd) ;mpv-socked mit tcp auf port 50100 verknüpfen // port der tcp-verbindung // mpv-socket-pfad (wird beim mpv-start als parameter definiert)
Delay(200) ;tick warten
so_ID = mpv_socket(1,mpvport) ;//1=verbinden,Port
If so_ID ;wenn verbunden
DisableGadget(1, #False)
DisableGadget(2, #False)
Else
SetGadgetText(1,"???")
SetGadgetText(2,"???")
EndIf
;- beginn ereignisschleife -------------------
Repeat ;ereignisschleife
Select WaitWindowEvent()
Case #PB_Event_CloseWindow ;wenn x gedrückt
mpv_socket(0,so_ID) ;tcp-verbindung trennen // 0=trennen, tcp-verbindungs-ID
Break ;aus schleife hüpfen
Case #PB_Event_Gadget ;wenn checkbox/button o.ä. gedruckt wurde
Select EventGadget() ;auswerten, welches gadget genau gedrückt wurde
Case 1 ;pause/Play taste
mpv_command(so_ID,GetGadgetState(1)) ;GetGadgetState(1) liefert 1, wenn gedrückt -> Pause // oder 0, wenn nicht gedrückt -> play
Case 2 ;zweite taste mpv beenden
mpv_command(so_ID,2)
Case 3 ;dritte taste
Debug "wupp_3 = " + Str(GetGadgetState(3))
EndSelect ;welches gadget
EndSelect ;welches fensterereignis
ForEver
End