Add support for IINA player (#360)

* Ädd support for IINA

* cleanup

* Add start background image

* Restore comment

* Support custom player path

* Update messages

* Separate IINA changes from python_mpv_jsonipc

* Do not show file info for our placeholder image in the UI

* Fix mpv socket

* Fix running IINA from frozen app

Apparently, `iina-cli` gets confused when launched from a frozen app
and automatically adds `--stdin` to its passed launch arguments.
But then, it waits for a file to be piped and, because there is none,
the player crashes almost immediately. Sending `--no-stdin` to the
process resolves the ambiguity and does not cause any harm if
Syncplay is started from sources.

* Pass again environment to the subprocess.Popen call that opens mpv

Related to: c07206c18992c1dca401b30a01b9f0fe54a71df5
This commit is contained in:
Alberto Sottile 2020-11-29 17:18:53 +01:00 committed by GitHub
parent 40fef45203
commit 9de3b4d86f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 222 additions and 44 deletions

View File

@ -139,6 +139,8 @@ USER_READY_MIN_VERSION = "1.3.0"
SHARED_PLAYLIST_MIN_VERSION = "1.4.0" SHARED_PLAYLIST_MIN_VERSION = "1.4.0"
CHAT_MIN_VERSION = "1.5.0" CHAT_MIN_VERSION = "1.5.0"
FEATURE_LIST_MIN_VERSION = "1.5.0" FEATURE_LIST_MIN_VERSION = "1.5.0"
IINA_PATHS = ['/Applications/IINA.app/Contents/MacOS/IINA']
MPC_PATHS = [ MPC_PATHS = [
r"c:\program files (x86)\mpc-hc\mpc-hc.exe", r"c:\program files (x86)\mpc-hc\mpc-hc.exe",
r"c:\program files\mpc-hc\mpc-hc.exe", r"c:\program files\mpc-hc\mpc-hc.exe",
@ -176,6 +178,7 @@ VLC_PATHS = [
] ]
VLC_ICONPATH = "vlc.png" VLC_ICONPATH = "vlc.png"
IINA_ICONPATH = "iina.png"
MPLAYER_ICONPATH = "mplayer.png" MPLAYER_ICONPATH = "mplayer.png"
MPV_ICONPATH = "mpv.png" MPV_ICONPATH = "mpv.png"
MPVNET_ICONPATH = "mpvnet.png" MPVNET_ICONPATH = "mpvnet.png"
@ -250,6 +253,13 @@ MPV_ARGS = {'force-window': 'yes',
'keep-open-pause': 'yes' 'keep-open-pause': 'yes'
} }
IINA_PROPERTIES = {'geometry': '25%+100+100',
'idle': 'yes',
'hr-seek': 'always',
'input-terminal': 'no',
'term-playing-msg': '<SyncplayUpdateFile>\nANS_filename=${filename}\nANS_length=${=duration:${=length:0}}\nANS_path=${path}\n</SyncplayUpdateFile>',
'keep-open-pause': 'yes',
}
MPV_NEW_VERSION = False MPV_NEW_VERSION = False
MPV_OSC_VISIBILITY_CHANGE_VERSION = False MPV_OSC_VISIBILITY_CHANGE_VERSION = False

View File

@ -113,7 +113,7 @@ de = {
"mpv-version-error": "Syncplay ist nicht kompatibel mit dieser Version von mpv. Bitte benutze eine andere Version (z.B. Git HEAD).", "mpv-version-error": "Syncplay ist nicht kompatibel mit dieser Version von mpv. Bitte benutze eine andere Version (z.B. Git HEAD).",
"mpv-failed-advice": "The reason mpv cannot start may be due to the use of unsupported command line arguments or an unsupported version of mpv.", # TODO: Translate "mpv-failed-advice": "The reason mpv cannot start may be due to the use of unsupported command line arguments or an unsupported version of mpv.", # TODO: Translate
"player-file-open-error": "Fehler beim Öffnen der Datei durch den Player", "player-file-open-error": "Fehler beim Öffnen der Datei durch den Player",
"player-path-error": "Ungültiger Player-Pfad. Unterstützte Player sind: mpv, mpv.net, VLC, MPC-HC, MPC-BE und mplayer2", "player-path-error": "Ungültiger Player-Pfad. Unterstützte Player sind: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2 und IINA",
"hostname-empty-error": "Hostname darf nicht leer sein", "hostname-empty-error": "Hostname darf nicht leer sein",
"empty-error": "{} darf nicht leer sein", # Configuration "empty-error": "{} darf nicht leer sein", # Configuration
"media-player-error": "Player-Fehler: \"{}\"", # Error line "media-player-error": "Player-Fehler: \"{}\"", # Error line
@ -124,7 +124,7 @@ de = {
"unable-to-start-client-error": "Client kann nicht gestartet werden", "unable-to-start-client-error": "Client kann nicht gestartet werden",
"player-path-config-error": "Player-Pfad ist nicht ordnungsgemäß gesetzt. Unterstützte Player sind: mpv, mpv.net, VLC, MPC-HC, MPC-BE und mplayer2", "player-path-config-error": "Player-Pfad ist nicht ordnungsgemäß gesetzt. Unterstützte Player sind: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2 und IINA",
"no-file-path-config-error": "Es muss eine Datei ausgewählt werden, bevor der Player gestartet wird.", "no-file-path-config-error": "Es muss eine Datei ausgewählt werden, bevor der Player gestartet wird.",
"no-hostname-config-error": "Hostname darf nicht leer sein", "no-hostname-config-error": "Hostname darf nicht leer sein",
"invalid-port-config-error": "Port muss gültig sein", "invalid-port-config-error": "Port muss gültig sein",
@ -381,7 +381,7 @@ de = {
"edit-rooms-tooltip": "Edit room list.", # TO DO: Translate "edit-rooms-tooltip": "Edit room list.", # TO DO: Translate
"executable-path-tooltip": "Pfad zum ausgewählten, unterstützten Mediaplayer (mpv, mpv.net, VLC, MPC-HC/BE or mplayer2).", "executable-path-tooltip": "Pfad zum ausgewählten, unterstützten Mediaplayer (mpv, mpv.net, VLC, MPC-HC/BE, mplayer2, oder IINA).",
"media-path-tooltip": "Pfad zum wiederzugebenden Video oder Stream. Notwendig für mplayer2.", "media-path-tooltip": "Pfad zum wiederzugebenden Video oder Stream. Notwendig für mplayer2.",
"player-arguments-tooltip": "Zusätzliche Kommandozeilenparameter/-schalter für diesen Mediaplayer.", "player-arguments-tooltip": "Zusätzliche Kommandozeilenparameter/-schalter für diesen Mediaplayer.",
"mediasearcdirectories-arguments-tooltip": "Verzeichnisse, in denen Syncplay nach Mediendateien suchen soll, z.B. wenn du die Click-to-switch-Funktion verwendest. Syncplay wird Unterverzeichnisse rekursiv durchsuchen.", # TODO: Translate Click-to-switch? (or use as name for feature) "mediasearcdirectories-arguments-tooltip": "Verzeichnisse, in denen Syncplay nach Mediendateien suchen soll, z.B. wenn du die Click-to-switch-Funktion verwendest. Syncplay wird Unterverzeichnisse rekursiv durchsuchen.", # TODO: Translate Click-to-switch? (or use as name for feature)

View File

@ -113,7 +113,7 @@ en = {
"mpv-version-error": "Syncplay is not compatible with this version of mpv. Please use a different version of mpv (e.g. Git HEAD).", "mpv-version-error": "Syncplay is not compatible with this version of mpv. Please use a different version of mpv (e.g. Git HEAD).",
"mpv-failed-advice": "The reason mpv cannot start may be due to the use of unsupported command line arguments or an unsupported version of mpv.", "mpv-failed-advice": "The reason mpv cannot start may be due to the use of unsupported command line arguments or an unsupported version of mpv.",
"player-file-open-error": "Player failed opening file", "player-file-open-error": "Player failed opening file",
"player-path-error": "Player path is not set properly. Supported players are: mpv, mpv.net, VLC, MPC-HC, MPC-BE and mplayer2", "player-path-error": "Player path is not set properly. Supported players are: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2, and IINA",
"hostname-empty-error": "Hostname can't be empty", "hostname-empty-error": "Hostname can't be empty",
"empty-error": "{} can't be empty", # Configuration "empty-error": "{} can't be empty", # Configuration
"media-player-error": "Media player error: \"{}\"", # Error line "media-player-error": "Media player error: \"{}\"", # Error line
@ -124,7 +124,7 @@ en = {
"unable-to-start-client-error": "Unable to start client", "unable-to-start-client-error": "Unable to start client",
"player-path-config-error": "Player path is not set properly. Supported players are: mpv, mpv.net, VLC, MPC-HC, MPC-BE and mplayer2.", "player-path-config-error": "Player path is not set properly. Supported players are: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2, and IINA.",
"no-file-path-config-error": "File must be selected before starting your player", "no-file-path-config-error": "File must be selected before starting your player",
"no-hostname-config-error": "Hostname can't be empty", "no-hostname-config-error": "Hostname can't be empty",
"invalid-port-config-error": "Port must be valid", "invalid-port-config-error": "Port must be valid",
@ -384,7 +384,7 @@ en = {
"edit-rooms-tooltip": "Edit room list.", "edit-rooms-tooltip": "Edit room list.",
"executable-path-tooltip": "Location of your chosen supported media player (mpv, mpv.net, VLC, MPC-HC/BE or mplayer2).", "executable-path-tooltip": "Location of your chosen supported media player (mpv, mpv.net, VLC, MPC-HC/BE, mplayer2 or IINA).",
"media-path-tooltip": "Location of video or stream to be opened. Necessary for mplayer2.", "media-path-tooltip": "Location of video or stream to be opened. Necessary for mplayer2.",
"player-arguments-tooltip": "Additional command line arguments / switches to pass on to this media player.", "player-arguments-tooltip": "Additional command line arguments / switches to pass on to this media player.",
"mediasearcdirectories-arguments-tooltip": "Directories where Syncplay will search for media files, e.g. when you are using the click to switch feature. Syncplay will look recursively through sub-folders.", "mediasearcdirectories-arguments-tooltip": "Directories where Syncplay will search for media files, e.g. when you are using the click to switch feature. Syncplay will look recursively through sub-folders.",

View File

@ -113,7 +113,7 @@ es = {
"mpv-version-error": "Syncplay no es compatible con esta versión de mpv. Por favor utiliza una versión diferente de mpv (p.ej. Git HEAD).", "mpv-version-error": "Syncplay no es compatible con esta versión de mpv. Por favor utiliza una versión diferente de mpv (p.ej. Git HEAD).",
"mpv-failed-advice": "The reason mpv cannot start may be due to the use of unsupported command line arguments or an unsupported version of mpv.", # TODO: Translate "mpv-failed-advice": "The reason mpv cannot start may be due to the use of unsupported command line arguments or an unsupported version of mpv.", # TODO: Translate
"player-file-open-error": "El reproductor falló al abrir el archivo", "player-file-open-error": "El reproductor falló al abrir el archivo",
"player-path-error": "La ruta del reproductor no está definida correctamente. Los reproductores soportados son: mpv, mpv.net, VLC, MPC-HC, MPC-BE y mplayer2", "player-path-error": "La ruta del reproductor no está definida correctamente. Los reproductores soportados son: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2, y IINA",
"hostname-empty-error": "El nombre del host no puede ser vacío", "hostname-empty-error": "El nombre del host no puede ser vacío",
"empty-error": "{} no puede ser vacío", # Configuration "empty-error": "{} no puede ser vacío", # Configuration
"media-player-error": "Error del reproductor multimedia: \"{}\"", # Error line "media-player-error": "Error del reproductor multimedia: \"{}\"", # Error line
@ -124,7 +124,7 @@ es = {
"unable-to-start-client-error": "No se logró iniciar el cliente", "unable-to-start-client-error": "No se logró iniciar el cliente",
"player-path-config-error": "La ruta del reproductor no está definida correctamente. Los reproductores soportados son: mpv, mpv.net, VLC, MPC-HC, MPC-BE y mplayer2.", "player-path-config-error": "La ruta del reproductor no está definida correctamente. Los reproductores soportados son: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2 y IINA.",
"no-file-path-config-error": "El archivo debe ser seleccionado antes de iniciar el reproductor", "no-file-path-config-error": "El archivo debe ser seleccionado antes de iniciar el reproductor",
"no-hostname-config-error": "El nombre del host no puede ser vacío", "no-hostname-config-error": "El nombre del host no puede ser vacío",
"invalid-port-config-error": "El puerto debe ser válido", "invalid-port-config-error": "El puerto debe ser válido",
@ -383,7 +383,7 @@ es = {
"edit-rooms-tooltip": "Edit room list.", # TO DO: Translate "edit-rooms-tooltip": "Edit room list.", # TO DO: Translate
"executable-path-tooltip": "Ubicación de tu reproductor multimedia compatible elegido (mpv, mpv.net, VLC, MPC-HC/BE o mplayer2).", "executable-path-tooltip": "Ubicación de tu reproductor multimedia compatible elegido (mpv, mpv.net, VLC, MPC-HC/BE, mplayer2 o IINA).",
"media-path-tooltip": "Ubicación del video o flujo que se abrirá. Necesario para mplayer2.", "media-path-tooltip": "Ubicación del video o flujo que se abrirá. Necesario para mplayer2.",
"player-arguments-tooltip": "Arguementos de línea de comandos adicionales / parámetros para pasar a este reproductor multimedia.", "player-arguments-tooltip": "Arguementos de línea de comandos adicionales / parámetros para pasar a este reproductor multimedia.",
"mediasearcdirectories-arguments-tooltip": "Directorios donde Syncplay buscará archivos de medios, p.ej. cuando estás usando la función \"clic para cambiar\". Syncplay buscará recursivamente a través de las subcarpetas.", "mediasearcdirectories-arguments-tooltip": "Directorios donde Syncplay buscará archivos de medios, p.ej. cuando estás usando la función \"clic para cambiar\". Syncplay buscará recursivamente a través de las subcarpetas.",

View File

@ -113,7 +113,7 @@ it = {
"mpv-version-error": "Syncplay non è compatibile con questa versione di mpv. Per favore usa un'altra versione di mpv (es. Git HEAD).", "mpv-version-error": "Syncplay non è compatibile con questa versione di mpv. Per favore usa un'altra versione di mpv (es. Git HEAD).",
"mpv-failed-advice": "The reason mpv cannot start may be due to the use of unsupported command line arguments or an unsupported version of mpv.", # TODO: Translate "mpv-failed-advice": "The reason mpv cannot start may be due to the use of unsupported command line arguments or an unsupported version of mpv.", # TODO: Translate
"player-file-open-error": "Il player non è riuscito ad aprire il file", "player-file-open-error": "Il player non è riuscito ad aprire il file",
"player-path-error": "Il path del player non è configurato correttamente. I player supportati sono: mpv, mpv.net, VLC, MPC-HC, MPC-BE e mplayer2", "player-path-error": "Il path del player non è configurato correttamente. I player supportati sono: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2 e IINA",
"hostname-empty-error": "Il campo hostname non può essere vuoto", "hostname-empty-error": "Il campo hostname non può essere vuoto",
"empty-error": "Il campo {} non può esssere vuoto", # Configuration "empty-error": "Il campo {} non può esssere vuoto", # Configuration
"media-player-error": "Errore media player: \"{}\"", # Error line "media-player-error": "Errore media player: \"{}\"", # Error line
@ -124,7 +124,7 @@ it = {
"unable-to-start-client-error": "Impossibile avviare il client", "unable-to-start-client-error": "Impossibile avviare il client",
"player-path-config-error": "Il percorso del player non è configurato correttamente. I player supportati sono: mpv, mpv.net, VLC, MPC-HC, MPC-BE e mplayer2.", "player-path-config-error": "Il percorso del player non è configurato correttamente. I player supportati sono: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2 e IINA.",
"no-file-path-config-error": "Deve essere selezionato un file prima di avviare il player", "no-file-path-config-error": "Deve essere selezionato un file prima di avviare il player",
"no-hostname-config-error": "Il campo hostname non può essere vuoto", "no-hostname-config-error": "Il campo hostname non può essere vuoto",
"invalid-port-config-error": "La porta deve essere valida", "invalid-port-config-error": "La porta deve essere valida",
@ -383,7 +383,7 @@ it = {
"edit-rooms-tooltip": "Edit room list.", # TO DO: Translate "edit-rooms-tooltip": "Edit room list.", # TO DO: Translate
"executable-path-tooltip": "Percorso del media player desiderato (scegliere tra mpv, mpv.net, VLC, MPC-HC/BE or mplayer2).", "executable-path-tooltip": "Percorso del media player desiderato (scegliere tra mpv, mpv.net, VLC, MPC-HC/BE, mplayer2 o IINA).",
"media-path-tooltip": "Percorso del video o stream da aprire. Necessario per mplayer2.", "media-path-tooltip": "Percorso del video o stream da aprire. Necessario per mplayer2.",
"player-arguments-tooltip": "Argomenti da linea di comando aggiuntivi da passare al media player scelto.", "player-arguments-tooltip": "Argomenti da linea di comando aggiuntivi da passare al media player scelto.",
"mediasearcdirectories-arguments-tooltip": "Cartelle dove Syncplay cercherà i file multimediali, es. quando usi la funzione click to switch. Syncplay cercherà anche nelle sottocartelle.", "mediasearcdirectories-arguments-tooltip": "Cartelle dove Syncplay cercherà i file multimediali, es. quando usi la funzione click to switch. Syncplay cercherà anche nelle sottocartelle.",

View File

@ -113,7 +113,7 @@ pt_BR = {
"mpv-version-error": "O motivo pelo qual o mpv não pode ser iniciado pode ser devido ao uso de argumentos da linha de comando não suportados ou a uma versão não suportada do mpv.", "mpv-version-error": "O motivo pelo qual o mpv não pode ser iniciado pode ser devido ao uso de argumentos da linha de comando não suportados ou a uma versão não suportada do mpv.",
"mpv-failed-advice": "The reason mpv cannot start may be due to the use of unsupported command line arguments or an unsupported version of mpv.", # TODO: Translate "mpv-failed-advice": "The reason mpv cannot start may be due to the use of unsupported command line arguments or an unsupported version of mpv.", # TODO: Translate
"player-file-open-error": "O reprodutor falhou ao abrir o arquivo", "player-file-open-error": "O reprodutor falhou ao abrir o arquivo",
"player-path-error": "O caminho até o arquivo executável do reprodutor não está configurado corretamente. Os reprodutores suportados são: mpv, mpv.net, VLC, MPC-HC, MPC-BE e mplayer2", "player-path-error": "O caminho até o arquivo executável do reprodutor não está configurado corretamente. Os reprodutores suportados são: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2 e IINA",
"hostname-empty-error": "O endereço do servidor não pode ser vazio", "hostname-empty-error": "O endereço do servidor não pode ser vazio",
"empty-error": "{} não pode ser vazio", # Configuration "empty-error": "{} não pode ser vazio", # Configuration
"media-player-error": "Erro do reprodutor de mídia: \"{}\"", # Error line "media-player-error": "Erro do reprodutor de mídia: \"{}\"", # Error line
@ -124,7 +124,7 @@ pt_BR = {
"unable-to-start-client-error": "Não foi possível iniciar o client", "unable-to-start-client-error": "Não foi possível iniciar o client",
"player-path-config-error": "O caminho até o arquivo executável do reprodutor não está configurado corretamente. Os reprodutores suportados são: mpv, mpv.net, VLC, MPC-HC, MPC-BE e mplayer2.", "player-path-config-error": "O caminho até o arquivo executável do reprodutor não está configurado corretamente. Os reprodutores suportados são: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2 e IINA.",
"no-file-path-config-error": "O arquivo deve ser selecionado antes de iniciar seu reprodutor", "no-file-path-config-error": "O arquivo deve ser selecionado antes de iniciar seu reprodutor",
"no-hostname-config-error": "O endereço do servidor não pode ser vazio", "no-hostname-config-error": "O endereço do servidor não pode ser vazio",
"invalid-port-config-error": "A porta deve ser válida", "invalid-port-config-error": "A porta deve ser válida",
@ -383,7 +383,7 @@ pt_BR = {
"edit-rooms-tooltip": "Edit room list.", # TO DO: Translate "edit-rooms-tooltip": "Edit room list.", # TO DO: Translate
"executable-path-tooltip": "Localização do seu reprodutor de mídia preferido (mpv, mpv.net, VLC, MPC-HC/BE ou mplayer2).", "executable-path-tooltip": "Localização do seu reprodutor de mídia preferido (mpv, mpv.net, VLC, MPC-HC/BE, mplayer2 ou IINA).",
"media-path-tooltip": "Localização do vídeo ou transmissão a ser aberto. Necessário com o mplayer2.", "media-path-tooltip": "Localização do vídeo ou transmissão a ser aberto. Necessário com o mplayer2.",
"player-arguments-tooltip": "Argumentos de comando de linha adicionais para serem repassados ao reprodutor de mídia.", "player-arguments-tooltip": "Argumentos de comando de linha adicionais para serem repassados ao reprodutor de mídia.",
"mediasearcdirectories-arguments-tooltip": "Diretório onde o Syncplay vai procurar por arquivos de mídia, por exemplo quando você estiver usando o recurso de clicar para mudar. O Syncplay irá procurar recursivamente pelas subpastas.", "mediasearcdirectories-arguments-tooltip": "Diretório onde o Syncplay vai procurar por arquivos de mídia, por exemplo quando você estiver usando o recurso de clicar para mudar. O Syncplay irá procurar recursivamente pelas subpastas.",

View File

@ -113,7 +113,7 @@ pt_PT = {
"mpv-version-error": "O Syncplay não é compatível com esta versão do mpv. Por favor, use uma versão diferente do mpv (por exemplo, Git HEAD).", "mpv-version-error": "O Syncplay não é compatível com esta versão do mpv. Por favor, use uma versão diferente do mpv (por exemplo, Git HEAD).",
"mpv-failed-advice": "O motivo pelo qual o mpv não pode ser iniciado pode ser devido ao uso de argumentos da linha de comando não suportados ou a uma versão não suportada do mpv.", # TODO: Translate "mpv-failed-advice": "O motivo pelo qual o mpv não pode ser iniciado pode ser devido ao uso de argumentos da linha de comando não suportados ou a uma versão não suportada do mpv.", # TODO: Translate
"player-file-open-error": "O reprodutor falhou ao abrir o ficheiro", "player-file-open-error": "O reprodutor falhou ao abrir o ficheiro",
"player-path-error": "O caminho até o ficheiro executável do reprodutor não está configurado corretamente. Os reprodutores suportados são: mpv, mpv.net, VLC, MPC-HC, MPC-BE e mplayer2", "player-path-error": "O caminho até o ficheiro executável do reprodutor não está configurado corretamente. Os reprodutores suportados são: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2 e IINA",
"hostname-empty-error": "O endereço do servidor não pode ser vazio", "hostname-empty-error": "O endereço do servidor não pode ser vazio",
"empty-error": "{} não pode ser vazio", # Configuration "empty-error": "{} não pode ser vazio", # Configuration
"media-player-error": "Erro do reprodutor de mídia: \"{}\"", # Error line "media-player-error": "Erro do reprodutor de mídia: \"{}\"", # Error line
@ -124,7 +124,7 @@ pt_PT = {
"unable-to-start-client-error": "Não foi possível iniciar o client", "unable-to-start-client-error": "Não foi possível iniciar o client",
"player-path-config-error": "O caminho até o ficheiro executável do reprodutor não está configurado corretamente. Os reprodutores suportados são: mpv, mpv.net, VLC, MPC-HC, MPC-BE e mplayer2.", "player-path-config-error": "O caminho até o ficheiro executável do reprodutor não está configurado corretamente. Os reprodutores suportados são: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2 e IINA.",
"no-file-path-config-error": "O ficheiro deve ser selecionado antes de iniciar seu reprodutor", "no-file-path-config-error": "O ficheiro deve ser selecionado antes de iniciar seu reprodutor",
"no-hostname-config-error": "O endereço do servidor não pode ser vazio", "no-hostname-config-error": "O endereço do servidor não pode ser vazio",
"invalid-port-config-error": "A porta deve ser válida", "invalid-port-config-error": "A porta deve ser válida",
@ -382,7 +382,7 @@ pt_PT = {
"edit-rooms-tooltip": "Edit room list.", # TO DO: Translate "edit-rooms-tooltip": "Edit room list.", # TO DO: Translate
"executable-path-tooltip": "Localização do seu reprodutor de mídia preferido (mpv, mpv.net, VLC, MPC-HC/BE ou mplayer2).", "executable-path-tooltip": "Localização do seu reprodutor de mídia preferido (mpv, mpv.net, VLC, MPC-HC/BE, mplayer2 ou IINA).",
"media-path-tooltip": "Localização do vídeo ou transmissão a ser aberto. Necessário com o mplayer2.", "media-path-tooltip": "Localização do vídeo ou transmissão a ser aberto. Necessário com o mplayer2.",
"player-arguments-tooltip": "Argumentos de comando de linha adicionais para serem repassados ao reprodutor de mídia.", "player-arguments-tooltip": "Argumentos de comando de linha adicionais para serem repassados ao reprodutor de mídia.",
"mediasearcdirectories-arguments-tooltip": "Pasta onde o Syncplay vai procurar por ficheiros de mídia, por exemplo quando você estiver usando o recurso de clicar para mudar. O Syncplay irá procurar recursivamente pelas subpastas.", "mediasearcdirectories-arguments-tooltip": "Pasta onde o Syncplay vai procurar por ficheiros de mídia, por exemplo quando você estiver usando o recurso de clicar para mudar. O Syncplay irá procurar recursivamente pelas subpastas.",

View File

@ -113,7 +113,7 @@ ru = {
"mpv-version-error": "Syncplay не совместим с данной версией mpv. Пожалуйста, используйте другую версию mpv (лучше свежайшую).", "mpv-version-error": "Syncplay не совместим с данной версией mpv. Пожалуйста, используйте другую версию mpv (лучше свежайшую).",
"mpv-failed-advice": "The reason mpv cannot start may be due to the use of unsupported command line arguments or an unsupported version of mpv.", # TODO: Translate "mpv-failed-advice": "The reason mpv cannot start may be due to the use of unsupported command line arguments or an unsupported version of mpv.", # TODO: Translate
"player-file-open-error": "Проигрыватель не может открыть файл.", "player-file-open-error": "Проигрыватель не может открыть файл.",
"player-path-error": "Путь к проигрывателю задан неверно. Supported players are: mpv, mpv.net, VLC, MPC-HC, MPC-BE and mplayer2.", # TODO: Translate last sentence "player-path-error": "Путь к проигрывателю задан неверно. Supported players are: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2 and IINA.", # TODO: Translate last sentence
"hostname-empty-error": "Имя пользователя не может быть пустым.", "hostname-empty-error": "Имя пользователя не может быть пустым.",
"empty-error": "{} не может быть пустым.", # Configuration "empty-error": "{} не может быть пустым.", # Configuration
"media-player-error": "Ошибка проигрывателя: \"{}\"", # Error line "media-player-error": "Ошибка проигрывателя: \"{}\"", # Error line
@ -124,7 +124,7 @@ ru = {
"unable-to-start-client-error": "Невозможно запустить клиент", "unable-to-start-client-error": "Невозможно запустить клиент",
"player-path-config-error": "Путь к проигрывателю установлен неверно. Supported players are: mpv, mpv.net, VLC, MPC-HC, MPC-BE and mplayer2", # To do: Translate end "player-path-config-error": "Путь к проигрывателю установлен неверно. Supported players are: mpv, mpv.net, VLC, MPC-HC, MPC-BE, mplayer2 and IINA", # To do: Translate end
"no-file-path-config-error": "Файл должен быть указан до включения проигрывателя", "no-file-path-config-error": "Файл должен быть указан до включения проигрывателя",
"no-hostname-config-error": "Имя сервера не может быть пустым", "no-hostname-config-error": "Имя сервера не может быть пустым",
"invalid-port-config-error": "Неверный номер порта", "invalid-port-config-error": "Неверный номер порта",
@ -386,7 +386,7 @@ ru = {
"edit-rooms-tooltip": "Edit room list.", # TO DO: Translate "edit-rooms-tooltip": "Edit room list.", # TO DO: Translate
"executable-path-tooltip": "Расположение Вашего видеопроигрывателя (mpv, mpv.net, VLC, MPC-HC/BE или mplayer2).", "executable-path-tooltip": "Расположение Вашего видеопроигрывателя (mpv, mpv.net, VLC, MPC-HC/BE, mplayer2, или IINA).",
"media-path-tooltip": "Расположение видеофайла или потока для просмотра. Обязательно для mplayer2.", # TODO: Confirm translation "media-path-tooltip": "Расположение видеофайла или потока для просмотра. Обязательно для mplayer2.", # TODO: Confirm translation
"player-arguments-tooltip": "Передавать дополнительные аргументы командной строки этому проигрывателю.", "player-arguments-tooltip": "Передавать дополнительные аргументы командной строки этому проигрывателю.",
"mediasearcdirectories-arguments-tooltip": "Папки, где Syncplay будет искать медиа файлы, включая подпапки.", "mediasearcdirectories-arguments-tooltip": "Папки, где Syncplay будет искать медиа файлы, включая подпапки.",

View File

@ -12,7 +12,12 @@ try:
except ImportError: except ImportError:
from syncplay.players.basePlayer import DummyPlayer from syncplay.players.basePlayer import DummyPlayer
MpcBePlayer = DummyPlayer MpcBePlayer = DummyPlayer
try:
from syncplay.players.iina import IinaPlayer
except ImportError:
from syncplay.players.basePlayer import DummyPlayer
IinaPlayer = DummyPlayer
def getAvailablePlayers(): def getAvailablePlayers():
return [MPCHCAPIPlayer, MpvPlayer, MpvnetPlayer, VlcPlayer, MpcBePlayer, MplayerPlayer] return [MPCHCAPIPlayer, MpvPlayer, MpvnetPlayer, VlcPlayer, MpcBePlayer, MplayerPlayer, IinaPlayer]

88
syncplay/players/iina.py Normal file
View File

@ -0,0 +1,88 @@
import os
from syncplay import constants
from syncplay.utils import findResourcePath
from syncplay.players.mpv import MpvPlayer
from syncplay.players.ipc_iina import IINA
class IinaPlayer(MpvPlayer):
@staticmethod
def run(client, playerPath, filePath, args):
constants.MPV_NEW_VERSION = True
constants.MPV_OSC_VISIBILITY_CHANGE_VERSION = True
return IinaPlayer(client, IinaPlayer.getExpandedPath(playerPath), filePath, args)
@staticmethod
def getStartupArgs(userArgs):
args = {}
if userArgs:
for argToAdd in userArgs:
if argToAdd.startswith('--'):
argToAdd = argToAdd[2:]
elif argToAdd.startswith('-'):
argToAdd = argToAdd[1:]
if argToAdd.strip() == "":
continue
if "=" in argToAdd:
(argName, argValue) = argToAdd.split("=", 1)
else:
argName = argToAdd
argValue = "yes"
args[argName] = argValue
return args
@staticmethod
def getDefaultPlayerPathsList():
l = []
for path in constants.IINA_PATHS:
p = IinaPlayer.getExpandedPath(path)
if p:
l.append(p)
return l
@staticmethod
def isValidPlayerPath(path):
if "iina-cli" in path or "iina-cli" in IinaPlayer.getExpandedPath(path):
return True
return False
@staticmethod
def getExpandedPath(playerPath):
if "iina-cli" in playerPath:
pass
elif "IINA.app/Contents/MacOS/IINA" in playerPath:
playerPath = os.path.join(os.path.dirname(playerPath), "iina-cli")
if os.access(playerPath, os.X_OK):
return playerPath
for path in os.environ['PATH'].split(':'):
path = os.path.join(os.path.realpath(path), playerPath)
if os.access(path, os.X_OK):
return path
return playerPath
@staticmethod
def getIconPath(path):
return constants.IINA_ICONPATH
def __init__(self, client, playerPath, filePath, args):
from twisted.internet import reactor
self.reactor = reactor
self._client = client
self._set_defaults()
self._playerIPCHandler = IINA
self._create_listener(playerPath, filePath, args)
def _preparePlayer(self):
for key, value in constants.IINA_PROPERTIES.items():
self._setProperty(key, value)
self._listener.sendLine(["load-script", findResourcePath("syncplayintf.lua")])
super()._preparePlayer()
def _onFileUpdate(self):
# do not show file info for our placeholder image in Syncplay UI
if self._filename == "iina-bkg.png":
return
else:
super()._onFileUpdate()

56
syncplay/players/ipc_iina.py Executable file
View File

@ -0,0 +1,56 @@
import os.path
import subprocess
import time
from syncplay.players.python_mpv_jsonipc.python_mpv_jsonipc import log, MPV, MPVError, MPVProcess
from syncplay.utils import resourcespath
class IINA(MPV):
"""The main IINA interface class. Use this to control the MPV player instantiated by IINA."""
def _start_mpv(self, ipc_socket, mpv_location, **kwargs):
# Attempt to start IINA 3 times.
for i in range(3):
try:
self.mpv_process = IINAProcess(ipc_socket, mpv_location, **kwargs)
break
except MPVError:
log.warning("IINA start failed.", exc_info=1)
continue
else:
raise MPVError("IINA process retry limit reached.")
class IINAProcess(MPVProcess):
"""
Manages an IINA process, ensuring the socket or pipe is available. (Internal)
"""
def _start_process(self, ipc_socket, args, env):
self.process = subprocess.Popen(args, env=env)
ipc_exists = False
for _ in range(100): # Give IINA 10 seconds to start.
time.sleep(0.1)
self.process.poll()
if os.path.exists(ipc_socket):
ipc_exists = True
log.debug("Found IINA socket.")
break
if self.process.returncode != 0: # iina-cli returns immediately after its start
log.error("IINA failed with returncode {0}.".format(self.process.returncode))
break
else:
self.process.terminate()
raise MPVError("IINA start timed out.")
if not ipc_exists or self.process.returncode != 0:
self.process.terminate()
raise MPVError("IINA not started.")
def _get_arglist(self, exec_location, **kwargs):
args = [exec_location]
args.append('--no-stdin')
args.append(resourcespath + 'iina-bkg.png')
self._set_default(kwargs, "mpv-input-ipc-server", self.ipc_socket)
args.extend("--{0}={1}".format(v[0].replace("_", "-"), self._mpv_fmt(v[1]))
for v in kwargs.items())
return args

View File

@ -504,6 +504,12 @@ class MpvPlayer(BasePlayer):
from twisted.internet import reactor from twisted.internet import reactor
self.reactor = reactor self.reactor = reactor
self._client = client self._client = client
self._set_defaults()
self._playerIPCHandler = MPV
self._create_listener(playerPath, filePath, args)
def _set_defaults(self):
self._paused = None self._paused = None
self._position = 0.0 self._position = 0.0
self._duration = None self._duration = None
@ -513,8 +519,10 @@ class MpvPlayer(BasePlayer):
self.lastLoadedTime = None self.lastLoadedTime = None
self.fileLoaded = False self.fileLoaded = False
self.delayedFilePath = None self.delayedFilePath = None
def _create_listener(self, playerPath, filePath, args):
try: try:
self._listener = self.__Listener(self, playerPath, filePath, args) self._listener = self.__Listener(self, self._playerIPCHandler, playerPath, filePath, args)
except ValueError: except ValueError:
self._client.ui.showMessage(getMessage("mplayer-file-required-notification")) self._client.ui.showMessage(getMessage("mplayer-file-required-notification"))
self._client.ui.showMessage(getMessage("mplayer-file-required-notification/example")) self._client.ui.showMessage(getMessage("mplayer-file-required-notification/example"))
@ -549,7 +557,8 @@ class MpvPlayer(BasePlayer):
self.lineReceived(text) self.lineReceived(text)
class __Listener(threading.Thread): class __Listener(threading.Thread):
def __init__(self, playerController, playerPath, filePath, args): def __init__(self, playerController, playerIPCHandler, playerPath, filePath, args):
self.playerIPCHandler = playerIPCHandler
self.playerPath = playerPath self.playerPath = playerPath
self.mpv_arguments = playerController.getStartupArgs(args) self.mpv_arguments = playerController.getStartupArgs(args)
self.mpv_running = True self.mpv_running = True
@ -594,7 +603,7 @@ class MpvPlayer(BasePlayer):
env['PYTHONPATH'] = pythonPath env['PYTHONPATH'] = pythonPath
try: try:
socket = self.mpv_arguments.get('input-ipc-server') socket = self.mpv_arguments.get('input-ipc-server')
self.mpvpipe = MPV(mpv_location=self.playerPath, ipc_socket=socket, loglevel="info", log_handler=self.__playerController.mpv_log_handler, quit_callback=self.stop_client, **self.mpv_arguments) self.mpvpipe = self.playerIPCHandler(mpv_location=self.playerPath, ipc_socket=socket, loglevel="info", log_handler=self.__playerController.mpv_log_handler, quit_callback=self.stop_client, env=env, **self.mpv_arguments)
except Exception as e: except Exception as e:
self.quitReason = getMessage("media-player-error").format(str(e)) + " " + getMessage("mpv-failed-advice") self.quitReason = getMessage("media-player-error").format(str(e)) + " " + getMessage("mpv-failed-advice")
self.__playerController.reactor.callFromThread(self.__playerController._client.ui.showErrorMessage, self.quitReason, True) self.__playerController.reactor.callFromThread(self.__playerController._client.ui.showErrorMessage, self.quitReason, True)

View File

@ -182,7 +182,7 @@ class MPVProcess:
""" """
Manages an MPV process, ensuring the socket or pipe is available. (Internal) Manages an MPV process, ensuring the socket or pipe is available. (Internal)
""" """
def __init__(self, ipc_socket, mpv_location=None, **kwargs): def __init__(self, ipc_socket, mpv_location=None, env=None, **kwargs):
""" """
Create and start the MPV process. Will block until socket/pipe is available. Create and start the MPV process. Will block until socket/pipe is available.
@ -198,7 +198,6 @@ class MPVProcess:
mpv_location = "mpv" mpv_location = "mpv"
log.debug("Staring MPV from {0}.".format(mpv_location)) log.debug("Staring MPV from {0}.".format(mpv_location))
ipc_socket_name = ipc_socket
if os.name == 'nt': if os.name == 'nt':
ipc_socket = "\\\\.\\pipe\\" + ipc_socket ipc_socket = "\\\\.\\pipe\\" + ipc_socket
@ -207,13 +206,11 @@ class MPVProcess:
log.debug("Using IPC socket {0} for MPV.".format(ipc_socket)) log.debug("Using IPC socket {0} for MPV.".format(ipc_socket))
self.ipc_socket = ipc_socket self.ipc_socket = ipc_socket
args = [mpv_location] args = self._get_arglist(mpv_location, **kwargs)
self._set_default(kwargs, "idle", True)
self._set_default(kwargs, "input_ipc_server", ipc_socket_name) self._start_process(ipc_socket, args, env=env)
self._set_default(kwargs, "input_terminal", False)
self._set_default(kwargs, "terminal", False) def _start_process(self, ipc_socket, args, env):
args.extend("--{0}={1}".format(v[0].replace("_", "-"), self._mpv_fmt(v[1]))
for v in kwargs.items())
self.process = subprocess.Popen(args) self.process = subprocess.Popen(args)
ipc_exists = False ipc_exists = False
for _ in range(100): # Give MPV 10 seconds to start. for _ in range(100): # Give MPV 10 seconds to start.
@ -238,6 +235,16 @@ class MPVProcess:
if key not in prop_dict: if key not in prop_dict:
prop_dict[key] = value prop_dict[key] = value
def _get_arglist(self, exec_location, **kwargs):
args = [exec_location]
self._set_default(kwargs, "idle", True)
self._set_default(kwargs, "input_ipc_server", self.ipc_socket)
self._set_default(kwargs, "input_terminal", False)
self._set_default(kwargs, "terminal", False)
args.extend("--{0}={1}".format(v[0].replace("_", "-"), self._mpv_fmt(v[1]))
for v in kwargs.items())
return args
def _mpv_fmt(self, data): def _mpv_fmt(self, data):
if data == True: if data == True:
return "yes" return "yes"
@ -405,16 +412,7 @@ class MPV:
ipc_socket = "/tmp/{0}".format(rand_file) ipc_socket = "/tmp/{0}".format(rand_file)
if start_mpv: if start_mpv:
# Attempt to start MPV 3 times. self._start_mpv(ipc_socket, mpv_location, **kwargs)
for i in range(3):
try:
self.mpv_process = MPVProcess(ipc_socket, mpv_location, **kwargs)
break
except MPVError:
log.warning("MPV start failed.", exc_info=1)
continue
else:
raise MPVError("MPV process retry limit reached.")
self.mpv_inter = MPVInter(ipc_socket, self._callback, self._quit_callback) self.mpv_inter = MPVInter(ipc_socket, self._callback, self._quit_callback)
self.properties = set(x.replace("-", "_") for x in self.command("get_property", "property-list")) self.properties = set(x.replace("-", "_") for x in self.command("get_property", "property-list"))
@ -451,6 +449,18 @@ class MPV:
if len(args) == 2 and args[0] == "custom-bind": if len(args) == 2 and args[0] == "custom-bind":
self.event_handler.put_task(self.key_bindings[args[1]]) self.event_handler.put_task(self.key_bindings[args[1]])
def _start_mpv(self, ipc_socket, mpv_location, **kwargs):
# Attempt to start MPV 3 times.
for i in range(3):
try:
self.mpv_process = MPVProcess(ipc_socket, mpv_location, **kwargs)
break
except MPVError:
log.warning("MPV start failed.", exc_info=1)
continue
else:
raise MPVError("MPV process retry limit reached.")
def _quit_callback(self): def _quit_callback(self):
""" """
Internal handler for quit events. Internal handler for quit events.

BIN
syncplay/resources/IINA.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
syncplay/resources/iina-bkg.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB