Merged upstream/master in master_local

This commit is contained in:
alby128 2017-12-11 18:10:03 +01:00
commit a58995edea
17 changed files with 225 additions and 156 deletions

View File

@ -651,6 +651,7 @@ guiIcons = ['resources/accept.png', 'resources/arrow_undo.png', 'resources/clock
'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png', 'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png',
'resources/timeline_marker.png','resources/control_play_blue.png', 'resources/timeline_marker.png','resources/control_play_blue.png',
'resources/mpc-hc.png','resources/mpc-hc64.png','resources/mplayer.png', 'resources/mpc-hc.png','resources/mpc-hc64.png','resources/mplayer.png',
'resources/mpc-be.png',
'resources/mpv.png','resources/vlc.png', 'resources/house.png', 'resources/film_link.png', 'resources/mpv.png','resources/vlc.png', 'resources/house.png', 'resources/film_link.png',
'resources/eye.png', 'resources/comments.png', 'resources/cog_delete.png', 'resources/chevrons_right.png', 'resources/eye.png', 'resources/comments.png', 'resources/cog_delete.png', 'resources/chevrons_right.png',
'resources/user_key.png', 'resources/lock.png', 'resources/key_go.png', 'resources/page_white_key.png', 'resources/user_key.png', 'resources/lock.png', 'resources/key_go.png', 'resources/page_white_key.png',

View File

@ -5,7 +5,7 @@
Principal author: Etoh Principal author: Etoh
Other contributors: DerGenaue, jb, Pilotat Other contributors: DerGenaue, jb, Pilotat
Project: http://syncplay.pl/ Project: http://syncplay.pl/
Version: 0.3.3 Version: 0.3.4
Note: Note:
* This interface module is intended to be used in conjunction with Syncplay. * This interface module is intended to be used in conjunction with Syncplay.
@ -19,7 +19,7 @@
Place the syncplay.lua file in the main (all user) VLC /lua/intf/ sub-directory: Place the syncplay.lua file in the main (all user) VLC /lua/intf/ sub-directory:
* Window: %ProgramFiles%\VideoLAN\VLC\lua\intf\ * Window: %ProgramFiles%\VideoLAN\VLC\lua\intf\
* Linux: /usr/lib/vlc/lua/intf/ or on some systems /usr/lib64/vlc/lua/intf/ (use whichever one already has .luac files in it) * Linux: /usr/lib/vlc/lua/intf/ or /usr/lib64/vlc/lua/intf/ or /usr/lib/x86_64-linux-gnu/vlc/lua/intf on some systems (look for where the .luac files are)
* Mac OS X: /Applications/VLC.app/Contents/MacOS/share/lua/intf/ * Mac OS X: /Applications/VLC.app/Contents/MacOS/share/lua/intf/
* FreeBSD, OpenBSD etc.: /usr/local/lib/vlc/lua/intf/ * FreeBSD, OpenBSD etc.: /usr/local/lib/vlc/lua/intf/
@ -84,7 +84,7 @@ You may also need to re-copy the syncplay.lua file when you update VLC.
--]==========================================================================] --]==========================================================================]
local connectorversion = "0.3.3" local connectorversion = "0.3.4"
local vlcversion = vlc.misc.version() local vlcversion = vlc.misc.version()
local vlcmajorversion = tonumber(vlcversion:sub(1,1)) -- get the major version of VLC local vlcmajorversion = tonumber(vlcversion:sub(1,1)) -- get the major version of VLC
local durationdelay = 500000 -- Pause for get_duration command etc for increased reliability (uses microseconds) local durationdelay = 500000 -- Pause for get_duration command etc for increased reliability (uses microseconds)
@ -243,7 +243,7 @@ function get_var( vartoget, fallbackvar )
errormsg = noinput errormsg = noinput
end end
if vlcmajorversion == 3 and vartoget == "time" then if vlcmajorversion > 2 and vartoget == "time" then
response = response / 1000000 response = response / 1000000
end end
@ -257,7 +257,7 @@ function set_var(vartoset, varvalue)
local errormsg local errormsg
local input = vlc.object.input() local input = vlc.object.input()
if vlcmajorversion == 3 and vartoset == "time" then if vlcmajorversion > 2 and vartoset == "time" then
varvalue = varvalue * 1000000 varvalue = varvalue * 1000000
end end

BIN
resources/mpc-be.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 890 B

View File

@ -1,4 +1,4 @@
version = '1.5.0' version = '1.5.0'
milestone = 'Yoitsu' milestone = 'Yoitsu'
release_number = '47' release_number = '50'
projectURL = 'http://syncplay.pl/' projectURL = 'http://syncplay.pl/'

View File

@ -83,8 +83,9 @@ COMMANDS_CREATE = ['c','create']
COMMANDS_AUTH = ['a','auth'] COMMANDS_AUTH = ['a','auth']
COMMANDS_TOGGLE = ['t','toggle'] COMMANDS_TOGGLE = ['t','toggle']
MPC_MIN_VER = "1.6.4" MPC_MIN_VER = "1.6.4"
MPC_BE_MIN_VER = "1.5.2.3123"
VLC_MIN_VERSION = "2.2.1" VLC_MIN_VERSION = "2.2.1"
VLC_INTERFACE_MIN_VERSION = "0.3.3" VLC_INTERFACE_MIN_VERSION = "0.3.4"
VLC_LATENCY_ERROR_THRESHOLD = 2.0 VLC_LATENCY_ERROR_THRESHOLD = 2.0
MPV_UNRESPONSIVE_THRESHOLD = 60.0 MPV_UNRESPONSIVE_THRESHOLD = 60.0
CONTROLLED_ROOMS_MIN_VERSION = "1.3.0" CONTROLLED_ROOMS_MIN_VERSION = "1.3.0"
@ -105,6 +106,12 @@ MPC_PATHS = [
r"c:\program files\combined community codec pack\mpc\mpc-hc.exe", r"c:\program files\combined community codec pack\mpc\mpc-hc.exe",
r"c:\program files\mpc homecinema (x64)\mpc-hc64.exe", r"c:\program files\mpc homecinema (x64)\mpc-hc64.exe",
] ]
MPC_BE_PATHS = [
r"c:\Program Files\MPC-BE x64\mpc-be64.exe",
r"c:\Program Files\MPC-BE x64\mpc-be.exe",
r"c:\Program Files\MPC-BE\mpc-be64.exe",
r"c:\Program Files\MPC-BE\mpc-be.exe"
]
MPLAYER_PATHS = ["mplayer2", "mplayer"] MPLAYER_PATHS = ["mplayer2", "mplayer"]
MPV_PATHS = ["mpv", "/opt/mpv/mpv", r"c:\program files\mpv\mpv.exe", r"c:\program files\mpv-player\mpv.exe", MPV_PATHS = ["mpv", "/opt/mpv/mpv", r"c:\program files\mpv\mpv.exe", r"c:\program files\mpv-player\mpv.exe",
r"c:\program Files (x86)\mpv\mpv.exe", r"c:\program Files (x86)\mpv-player\mpv.exe", r"c:\program Files (x86)\mpv\mpv.exe", r"c:\program Files (x86)\mpv-player\mpv.exe",
@ -124,6 +131,7 @@ MPLAYER_ICONPATH = "mplayer.png"
MPV_ICONPATH = "mpv.png" MPV_ICONPATH = "mpv.png"
MPC_ICONPATH = "mpc-hc.png" MPC_ICONPATH = "mpc-hc.png"
MPC64_ICONPATH = "mpc-hc64.png" MPC64_ICONPATH = "mpc-hc64.png"
MPC_BE_ICONPATH = "mpc-be.png"
MPV_ERROR_MESSAGES_TO_REPEAT = ['[ytdl_hook] Your version of youtube-dl is too old', '[ytdl_hook] youtube-dl failed', 'Failed to recognize file format.'] MPV_ERROR_MESSAGES_TO_REPEAT = ['[ytdl_hook] Your version of youtube-dl is too old', '[ytdl_hook] youtube-dl failed', 'Failed to recognize file format.']
@ -173,8 +181,8 @@ MPV_SLAVE_ARGS_NEW = ['--term-playing-msg=<SyncplayUpdateFile>\nANS_filename=${f
MPV_NEW_VERSION = False MPV_NEW_VERSION = False
VLC_SLAVE_ARGS = ['--extraintf=luaintf', '--lua-intf=syncplay', '--no-quiet', '--no-input-fast-seek', VLC_SLAVE_ARGS = ['--extraintf=luaintf', '--lua-intf=syncplay', '--no-quiet', '--no-input-fast-seek',
'--play-and-pause', '--start-time=0'] '--play-and-pause', '--start-time=0']
VLC_SLAVE_OSX_ARGS = ['--verbose=2', '--no-file-logging'] VLC_SLAVE_MACOS_ARGS = ['--verbose=2', '--no-file-logging']
VLC_SLAVE_NONOSX_ARGS = ['--no-one-instance', '--no-one-instance-when-started-from-file'] VLC_SLAVE_NONMACOS_ARGS = ['--no-one-instance', '--no-one-instance-when-started-from-file']
MPV_SUPERSEDE_IF_DUPLICATE_COMMANDS = ["no-osd set time-pos ", "loadfile "] MPV_SUPERSEDE_IF_DUPLICATE_COMMANDS = ["no-osd set time-pos ", "loadfile "]
MPV_REMOVE_BOTH_IF_DUPLICATE_COMMANDS = ["cycle pause"] MPV_REMOVE_BOTH_IF_DUPLICATE_COMMANDS = ["cycle pause"]
MPLAYER_ANSWER_REGEX = "^ANS_([a-zA-Z_-]+)=(.+)$|^(Exiting)\.\.\. \((.+)\)$" MPLAYER_ANSWER_REGEX = "^ANS_([a-zA-Z_-]+)=(.+)$|^(Exiting)\.\.\. \((.+)\)$"
@ -216,4 +224,10 @@ SYNCPLAY_PUBLIC_SERVER_LIST_URL = u"http://syncplay.pl/listpublicservers?{}" # P
DEFAULT_TRUSTED_DOMAINS = [u"youtube.com",u"youtu.be"] DEFAULT_TRUSTED_DOMAINS = [u"youtube.com",u"youtu.be"]
TRUSTABLE_WEB_PROTOCOLS = [u"http://www.",u"https://www.",u"http://",u"https://"] TRUSTABLE_WEB_PROTOCOLS = [u"http://www.",u"https://www.",u"http://",u"https://"]
PRIVATE_FILE_FIELDS = ["path"] PRIVATE_FILE_FIELDS = ["path"]
OS_WINDOWS = "win"
OS_LINUX = "linux"
OS_MACOS = "darwin"
OS_BSD = "freebsd"
OS_DRAGONFLY = "dragonfly"

View File

@ -108,9 +108,10 @@ de = {
"server-timeout-error" : u"Timeout: Verbindung zum Server fehlgeschlagen", "server-timeout-error" : u"Timeout: Verbindung zum Server fehlgeschlagen",
"mpc-slave-error" : u"Kann MPC nicht im Slave-Modus starten!", "mpc-slave-error" : u"Kann MPC nicht im Slave-Modus starten!",
"mpc-version-insufficient-error" : u"MPC-Version nicht ausreichend, bitte nutze `mpc-hc` >= `{}`", "mpc-version-insufficient-error" : u"MPC-Version nicht ausreichend, bitte nutze `mpc-hc` >= `{}`",
"mpc-be-version-insufficient-error" : u"MPC-Version nicht ausreichend, bitte nutze `mpc-be` >= `{}`",
"mpv-version-error" : u"Syncplay ist nicht kompatibel mit dieser Version von mpv. Bitte benutze eine andere Version (z.B. Git HEAD).", "mpv-version-error" : u"Syncplay ist nicht kompatibel mit dieser Version von mpv. Bitte benutze eine andere Version (z.B. Git HEAD).",
"player-file-open-error" : u"Fehler beim Öffnen der Datei durch den Player", "player-file-open-error" : u"Fehler beim Öffnen der Datei durch den Player",
"player-path-error" : u"Ungültiger Player-Pfad. Supported players are: mpv, VLC, MPC-HC and mplayer2", # To do: Translate end "player-path-error" : u"Ungültiger Player-Pfad. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2", # To do: Translate end
"hostname-empty-error" : u"Hostname darf nicht leer sein", "hostname-empty-error" : u"Hostname darf nicht leer sein",
"empty-error" : u"{} darf nicht leer sein", # Configuration "empty-error" : u"{} darf nicht leer sein", # Configuration
"media-player-error": u"Player-Fehler: \"{}\"", # Error line "media-player-error": u"Player-Fehler: \"{}\"", # Error line
@ -120,7 +121,7 @@ de = {
"unable-to-start-client-error" : u"Client kann nicht gestartet werden", "unable-to-start-client-error" : u"Client kann nicht gestartet werden",
"player-path-config-error": u"Player-Pfad ist nicht ordnungsgemäß gesetzt. Supported players are: mpv, VLC, MPC-HC and mplayer2.", # To do: Translate end "player-path-config-error": u"Player-Pfad ist nicht ordnungsgemäß gesetzt. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2.", # To do: Translate end
"no-file-path-config-error": u"Es muss eine Datei ausgewählt werden, bevor der Player gestartet wird.", "no-file-path-config-error": u"Es muss eine Datei ausgewählt werden, bevor der Player gestartet wird.",
"no-hostname-config-error": u"Hostname darf nicht leer sein", "no-hostname-config-error": u"Hostname darf nicht leer sein",
"invalid-port-config-error" : u"Port muss gültig sein", "invalid-port-config-error" : u"Port muss gültig sein",
@ -151,7 +152,7 @@ de = {
"failed-to-load-server-list-error" : u"Konnte die Liste der öffentlichen Server nicht laden. Bitte besuche http://www.syncplay.pl/ [Englisch] mit deinem Browser.", "failed-to-load-server-list-error" : u"Konnte die Liste der öffentlichen Server nicht laden. Bitte besuche http://www.syncplay.pl/ [Englisch] mit deinem Browser.",
# Client arguments # Client arguments
"argument-description" : u'Syncplay ist eine Anwendung um mehrere MPlayer, MPC-HC und VLC-Instanzen über das Internet zu synchronisieren.', "argument-description" : u'Syncplay ist eine Anwendung um mehrere MPlayer, MPC-HC, MPC-BE und VLC-Instanzen über das Internet zu synchronisieren.',
"argument-epilog" : u'Wenn keine Optionen angegeben sind, werden die _config-Werte verwendet', "argument-epilog" : u'Wenn keine Optionen angegeben sind, werden die _config-Werte verwendet',
"nogui-argument" : u'Keine GUI anzeigen', "nogui-argument" : u'Keine GUI anzeigen',
"host-argument" : u'Server-Adresse', "host-argument" : u'Server-Adresse',
@ -195,7 +196,7 @@ de = {
"filename-privacy-label" : u"Dateiname:", "filename-privacy-label" : u"Dateiname:",
"filesize-privacy-label" : u"Dateigröße:", "filesize-privacy-label" : u"Dateigröße:",
"checkforupdatesautomatically-label" : u"Automatisch nach Updates suchen", "checkforupdatesautomatically-label" : u"Automatisch nach Updates suchen",
"slowondesync-label" : u"Verlangsamen wenn nicht synchron (nicht unterstützt mit MPC-HC)", "slowondesync-label" : u"Verlangsamen wenn nicht synchron (nicht unterstützt mit MPC-HC/BE)",
"dontslowdownwithme-label" : u"Nie verlangsamen oder andere zurückspulen (Experimentell)", "dontslowdownwithme-label" : u"Nie verlangsamen oder andere zurückspulen (Experimentell)",
"pausing-title" : u"Pausing", # TODO: Translate "pausing-title" : u"Pausing", # TODO: Translate
"pauseonleave-label" : u"Pausieren wenn ein Benutzer austritt", "pauseonleave-label" : u"Pausieren wenn ein Benutzer austritt",
@ -320,7 +321,7 @@ de = {
"password-tooltip" : u"Passwörter sind nur bei Verbindung zu privaten Servern nötig.", "password-tooltip" : u"Passwörter sind nur bei Verbindung zu privaten Servern nötig.",
"room-tooltip" : u"Der Raum, der betreten werden soll, kann ein x-beliebiger sein. Allerdings werden nur Clients im selben Raum synchronisiert.", "room-tooltip" : u"Der Raum, der betreten werden soll, kann ein x-beliebiger sein. Allerdings werden nur Clients im selben Raum synchronisiert.",
"executable-path-tooltip" : u"Pfad zum ausgewählten, unterstützten Mediaplayer (MPC-HC, VLC, mplayer2 or mpv).", "executable-path-tooltip" : u"Pfad zum ausgewählten, unterstützten Mediaplayer (MPC-HC, MPC-BE, VLC, mplayer2 or mpv).",
"media-path-tooltip" : u"Pfad zum wiederzugebenden Video oder Stream. Notwendig für mplayer2.", # TODO: Confirm translation "media-path-tooltip" : u"Pfad zum wiederzugebenden Video oder Stream. Notwendig für mplayer2.", # TODO: Confirm translation
"player-arguments-tooltip" : u"Zusätzliche Kommandozeilenparameter / -schalter für diesen Mediaplayer.", "player-arguments-tooltip" : u"Zusätzliche Kommandozeilenparameter / -schalter für diesen Mediaplayer.",
"mediasearcdirectories-arguments-tooltip" : u"Verzeichnisse, in denen Syncplay nach Mediendateien suchen soll, z.B. wenn du das Click-to-switch-Feature verwendest. Syncplay wird rekursiv Unterordner durchsuchen.", # TODO: Translate Click-to-switch? (or use as name for feature) "mediasearcdirectories-arguments-tooltip" : u"Verzeichnisse, in denen Syncplay nach Mediendateien suchen soll, z.B. wenn du das Click-to-switch-Feature verwendest. Syncplay wird rekursiv Unterordner durchsuchen.", # TODO: Translate Click-to-switch? (or use as name for feature)
@ -383,7 +384,7 @@ de = {
"no-salt-notification" : u"WICHTIGER HINWEIS: Damit von dem Server generierte Passwörter für geführte Räume auch nach einem Serverneustart funktionieren, starte den Server mit dem folgenden Parameter: --salt {}", #Salt "no-salt-notification" : u"WICHTIGER HINWEIS: Damit von dem Server generierte Passwörter für geführte Räume auch nach einem Serverneustart funktionieren, starte den Server mit dem folgenden Parameter: --salt {}", #Salt
# Server arguments # Server arguments
"server-argument-description" : u'Anwendung, um mehrere MPlayer, MPC-HC und VLC-Instanzen über das Internet zu synchronisieren. Server', "server-argument-description" : u'Anwendung, um mehrere MPlayer, MPC-HC/BE und VLC-Instanzen über das Internet zu synchronisieren. Server',
"server-argument-epilog" : u'Wenn keine Optionen angegeben sind, werden die _config-Werte verwendet', "server-argument-epilog" : u'Wenn keine Optionen angegeben sind, werden die _config-Werte verwendet',
"server-port-argument" : u'Server TCP-Port', "server-port-argument" : u'Server TCP-Port',
"server-password-argument" : u'Server Passwort', "server-password-argument" : u'Server Passwort',

View File

@ -107,9 +107,10 @@ en = {
"server-timeout-error" : "Connection with server timed out", "server-timeout-error" : "Connection with server timed out",
"mpc-slave-error" : "Unable to start MPC in slave mode!", "mpc-slave-error" : "Unable to start MPC in slave mode!",
"mpc-version-insufficient-error" : "MPC version not sufficient, please use `mpc-hc` >= `{}`", "mpc-version-insufficient-error" : "MPC version not sufficient, please use `mpc-hc` >= `{}`",
"mpc-be-version-insufficient-error" : "MPC version not sufficient, please use `mpc-be` >= `{}`",
"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).",
"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, VLC, MPC-HC and mplayer2", "player-path-error" : "Player path is not set properly. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2",
"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
@ -119,7 +120,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, VLC, MPC-HC and mplayer2.", "player-path-config-error": "Player path is not set properly. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2.",
"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",
@ -149,7 +150,7 @@ en = {
"failed-to-load-server-list-error" : u"Failed to load public server list. Please visit http://www.syncplay.pl/ in your browser.", "failed-to-load-server-list-error" : u"Failed to load public server list. Please visit http://www.syncplay.pl/ in your browser.",
# Client arguments # Client arguments
"argument-description" : 'Solution to synchronize playback of multiple MPlayer and MPC-HC instances over the network.', "argument-description" : 'Solution to synchronize playback of multiple media player instances over the network.',
"argument-epilog" : 'If no options supplied _config values will be used', "argument-epilog" : 'If no options supplied _config values will be used',
"nogui-argument" : 'show no GUI', "nogui-argument" : 'show no GUI',
"host-argument" : 'server\'s address', "host-argument" : 'server\'s address',
@ -193,7 +194,7 @@ en = {
"filename-privacy-label" : "Filename information:", "filename-privacy-label" : "Filename information:",
"filesize-privacy-label" : "File size information:", "filesize-privacy-label" : "File size information:",
"checkforupdatesautomatically-label" : "Check for Syncplay updates automatically", "checkforupdatesautomatically-label" : "Check for Syncplay updates automatically",
"slowondesync-label" : "Slow down on minor desync (not supported on MPC-HC)", "slowondesync-label" : "Slow down on minor desync (not supported on MPC-HC/BE)",
"rewindondesync-label" : "Rewind on major desync (recommended)", "rewindondesync-label" : "Rewind on major desync (recommended)",
"fastforwardondesync-label" : "Fast-forward if lagging behind (recommended)", "fastforwardondesync-label" : "Fast-forward if lagging behind (recommended)",
"dontslowdownwithme-label" : "Never slow down or rewind others (experimental)", "dontslowdownwithme-label" : "Never slow down or rewind others (experimental)",
@ -320,7 +321,7 @@ en = {
"password-tooltip" : "Passwords are only needed for connecting to private servers.", "password-tooltip" : "Passwords are only needed for connecting to private servers.",
"room-tooltip" : "Room to join upon connection can be almost anything, but you will only be synchronised with people in the same room.", "room-tooltip" : "Room to join upon connection can be almost anything, but you will only be synchronised with people in the same room.",
"executable-path-tooltip" : "Location of your chosen supported media player (mpv, VLC, MPC-HC or mplayer2).", "executable-path-tooltip" : "Location of your chosen supported media player (mpv, VLC, MPC-HC/BE or mplayer2).",
"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" : u"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" : u"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.",
@ -332,7 +333,7 @@ en = {
"privacy-sendhashed-tooltip" : "Send a hashed version of the information, making it less visible to other clients.", "privacy-sendhashed-tooltip" : "Send a hashed version of the information, making it less visible to other clients.",
"privacy-dontsend-tooltip" : "Do not send this information to the server. This provides for maximum privacy.", "privacy-dontsend-tooltip" : "Do not send this information to the server. This provides for maximum privacy.",
"checkforupdatesautomatically-tooltip" : "Regularly check with the Syncplay website to see whether a new version of Syncplay is available.", "checkforupdatesautomatically-tooltip" : "Regularly check with the Syncplay website to see whether a new version of Syncplay is available.",
"slowondesync-tooltip" : "Reduce playback rate temporarily when needed to bring you back in sync with other viewers. Not supported on MPC-HC.", "slowondesync-tooltip" : "Reduce playback rate temporarily when needed to bring you back in sync with other viewers. Not supported on MPC-HC/BE.",
"dontslowdownwithme-tooltip" : "Means others do not get slowed down or rewinded if your playback is lagging. Useful for room operators.", "dontslowdownwithme-tooltip" : "Means others do not get slowed down or rewinded if your playback is lagging. Useful for room operators.",
"pauseonleave-tooltip" : "Pause playback if you get disconnected or someone leaves from your room.", "pauseonleave-tooltip" : "Pause playback if you get disconnected or someone leaves from your room.",
"readyatstart-tooltip" : "Set yourself as 'ready' at start (otherwise you are set as 'not ready' until you change your readiness state)", "readyatstart-tooltip" : "Set yourself as 'ready' at start (otherwise you are set as 'not ready' until you change your readiness state)",
@ -382,7 +383,7 @@ en = {
# Server arguments # Server arguments
"server-argument-description" : 'Solution to synchronize playback of multiple MPlayer and MPC-HC instances over the network. Server instance', "server-argument-description" : 'Solution to synchronize playback of multiple MPlayer and MPC-HC/BE instances over the network. Server instance',
"server-argument-epilog" : 'If no options supplied _config values will be used', "server-argument-epilog" : 'If no options supplied _config values will be used',
"server-port-argument" : 'server TCP port', "server-port-argument" : 'server TCP port',
"server-password-argument" : 'server password', "server-password-argument" : 'server password',

View File

@ -108,9 +108,10 @@ ru = {
"server-timeout-error" : u"Подключение к серверу превысило лимит времени", "server-timeout-error" : u"Подключение к серверу превысило лимит времени",
"mpc-slave-error" : u"Невозможно запустить MPC в slave режиме!", "mpc-slave-error" : u"Невозможно запустить MPC в slave режиме!",
"mpc-version-insufficient-error" : u"Версия MPC слишком старая, пожалуйста, используйте `mpc-hc` >= `{}`", "mpc-version-insufficient-error" : u"Версия MPC слишком старая, пожалуйста, используйте `mpc-hc` >= `{}`",
"mpc-be-version-insufficient-error" : u"Версия MPC слишком старая, пожалуйста, используйте `mpc-be` >= `{}`",
"mpv-version-error" : u"Syncplay не совместим с данной версией mpv. Пожалуйста, используйте другую версию mpv (лучше свежайшую).", "mpv-version-error" : u"Syncplay не совместим с данной версией mpv. Пожалуйста, используйте другую версию mpv (лучше свежайшую).",
"player-file-open-error" : u"Проигрыватель не может открыть файл.", "player-file-open-error" : u"Проигрыватель не может открыть файл.",
"player-path-error" : u"Путь к проигрывателю задан неверно. Supported players are: mpv, VLC, MPC-HC and mplayer2.", # TODO: Translate last sentence "player-path-error" : u"Путь к проигрывателю задан неверно. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2.", # TODO: Translate last sentence
"hostname-empty-error" : u"Имя пользователя не может быть пустым.", "hostname-empty-error" : u"Имя пользователя не может быть пустым.",
"empty-error" : u"{} не может быть пустым.", # Configuration "empty-error" : u"{} не может быть пустым.", # Configuration
"media-player-error" : u"Ошибка проигрывателя: \"{}\"", # Error line "media-player-error" : u"Ошибка проигрывателя: \"{}\"", # Error line
@ -120,7 +121,7 @@ ru = {
"unable-to-start-client-error" : u"Невозможно запустить клиент", "unable-to-start-client-error" : u"Невозможно запустить клиент",
"player-path-config-error": u"Путь к проигрывателю установлен неверно. Supported players are: mpv, VLC, MPC-HC and mplayer2", # To do: Translate end "player-path-config-error": u"Путь к проигрывателю установлен неверно. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2", # To do: Translate end
"no-file-path-config-error" : u"Файл должен быть указан до включения проигрывателя", "no-file-path-config-error" : u"Файл должен быть указан до включения проигрывателя",
"no-hostname-config-error": u"Имя сервера не может быть пустым", "no-hostname-config-error": u"Имя сервера не может быть пустым",
"invalid-port-config-error" : u"Неверный номер порта", "invalid-port-config-error" : u"Неверный номер порта",
@ -151,7 +152,7 @@ ru = {
"failed-to-load-server-list-error" : u"Не удалось загрузить список публичных серверов. Откройте http://www.syncplay.pl/ через браузер.", "failed-to-load-server-list-error" : u"Не удалось загрузить список публичных серверов. Откройте http://www.syncplay.pl/ через браузер.",
# Client arguments # Client arguments
"argument-description" : u'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC через Интернет.', "argument-description" : u'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC/BE через Интернет.',
"argument-epilog" : u'Если параметр не будет передан, то будет использоваться значение, указанное в _config.', "argument-epilog" : u'Если параметр не будет передан, то будет использоваться значение, указанное в _config.',
"nogui-argument" : u'не использовать GUI', "nogui-argument" : u'не использовать GUI',
"host-argument" : u'адрес сервера', "host-argument" : u'адрес сервера',
@ -195,7 +196,7 @@ ru = {
"filename-privacy-label" : u"Имя файла:", "filename-privacy-label" : u"Имя файла:",
"filesize-privacy-label" : u"Размер файла:", "filesize-privacy-label" : u"Размер файла:",
"checkforupdatesautomatically-label" : u"Проверять обновления автоматически", "checkforupdatesautomatically-label" : u"Проверять обновления автоматически",
"slowondesync-label" : u"Замедлять при небольших рассинхронизациях (не поддерживаетя в MPC-HC)", "slowondesync-label" : u"Замедлять при небольших рассинхронизациях (не поддерживаетя в MPC-HC/BE)",
"rewindondesync-label" : u"Перемотка при больших рассинхронизациях (настоятельно рекомендуется)", "rewindondesync-label" : u"Перемотка при больших рассинхронизациях (настоятельно рекомендуется)",
"dontslowdownwithme-label" : u"Никогда не замедлять и не перематывать видео другим (функция тестируется)", "dontslowdownwithme-label" : u"Никогда не замедлять и не перематывать видео другим (функция тестируется)",
"pausing-title" : u"Приостановка", "pausing-title" : u"Приостановка",
@ -322,7 +323,7 @@ ru = {
"password-tooltip" : u"Пароли нужны для подключения к приватным серверам.", "password-tooltip" : u"Пароли нужны для подключения к приватным серверам.",
"room-tooltip" : u"Комната, в которую Вы попадете сразу после подключения. Синхронизация возможна только между людьми в одной и той же комнате.", "room-tooltip" : u"Комната, в которую Вы попадете сразу после подключения. Синхронизация возможна только между людьми в одной и той же комнате.",
"executable-path-tooltip" : u"Расположение Вашего видеопроигрывателя (MPC-HC, VLC, mplayer2 или mpv).", "executable-path-tooltip" : u"Расположение Вашего видеопроигрывателя (MPC-HC, MPC-BE, VLC, mplayer2 или mpv).",
"media-path-tooltip" : u"Расположение видеофайла или потока для просмотра. Обязательно для mplayer2.", # TODO: Confirm translation "media-path-tooltip" : u"Расположение видеофайла или потока для просмотра. Обязательно для mplayer2.", # TODO: Confirm translation
"player-arguments-tooltip" : u"Передавать дополнительные аргументы командной строки этому проигрывателю.", "player-arguments-tooltip" : u"Передавать дополнительные аргументы командной строки этому проигрывателю.",
"mediasearcdirectories-arguments-tooltip" : u"Папки, где Syncplay будет искать медиа файлы, включая подпапки.", "mediasearcdirectories-arguments-tooltip" : u"Папки, где Syncplay будет искать медиа файлы, включая подпапки.",
@ -334,7 +335,7 @@ ru = {
"privacy-sendhashed-tooltip" : u"Отправляет хэш-сумму этой информации, делая ее невидимой для других пользователей.", "privacy-sendhashed-tooltip" : u"Отправляет хэш-сумму этой информации, делая ее невидимой для других пользователей.",
"privacy-dontsend-tooltip" : u"Не отправлять эту информацию на сервер. Предоставляет наибольшую приватность.", "privacy-dontsend-tooltip" : u"Не отправлять эту информацию на сервер. Предоставляет наибольшую приватность.",
"checkforupdatesautomatically-tooltip" : u"Syncplay будет регулярно заходить на сайт и проверять наличие новых версий.", "checkforupdatesautomatically-tooltip" : u"Syncplay будет регулярно заходить на сайт и проверять наличие новых версий.",
"slowondesync-tooltip" : u"Временно уменьшить скорость воспроизведения в целях синхронизации с другими зрителями. Не поддерживается в MPC-HC.", "slowondesync-tooltip" : u"Временно уменьшить скорость воспроизведения в целях синхронизации с другими зрителями. Не поддерживается в MPC-HC/BE.",
"dontslowdownwithme-tooltip" : u"Ваши лаги не будут влиять на других зрителей.", "dontslowdownwithme-tooltip" : u"Ваши лаги не будут влиять на других зрителей.",
"pauseonleave-tooltip" : u"Приостановить воспроизведение, если Вы покинули комнату или кто-то из зрителей отключился от сервера.", "pauseonleave-tooltip" : u"Приостановить воспроизведение, если Вы покинули комнату или кто-то из зрителей отключился от сервера.",
"readyatstart-tooltip" : u"Отметить Вас готовым к просмотру сразу же (по умолчанию Вы отмечены не готовым)", "readyatstart-tooltip" : u"Отметить Вас готовым к просмотру сразу же (по умолчанию Вы отмечены не готовым)",
@ -383,7 +384,7 @@ ru = {
"no-salt-notification" : u"ВНИМАНИЕ: Чтобы сгенерированные сервером пароли операторов комнат работали после перезагрузки сервера, необходимо указать следующий аргумент командной строки при запуске сервера Syncplay: --salt {}", #Salt "no-salt-notification" : u"ВНИМАНИЕ: Чтобы сгенерированные сервером пароли операторов комнат работали после перезагрузки сервера, необходимо указать следующий аргумент командной строки при запуске сервера Syncplay: --salt {}", #Salt
# Server arguments # Server arguments
"server-argument-description" : u'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC через Интернет. Серверная часть', "server-argument-description" : u'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC/BE через Интернет. Серверная часть',
"server-argument-epilog" : u'Если параметр не будет передан, то будет использоваться значение, указанное в _config.', "server-argument-epilog" : u'Если параметр не будет передан, то будет использоваться значение, указанное в _config.',
"server-port-argument" : u'номер TCP порта сервера', "server-port-argument" : u'номер TCP порта сервера',
"server-password-argument" : u'пароль к серверу', "server-password-argument" : u'пароль к серверу',

View File

@ -6,6 +6,11 @@ try:
except ImportError: except ImportError:
from syncplay.players.basePlayer import DummyPlayer from syncplay.players.basePlayer import DummyPlayer
MPCHCAPIPlayer = DummyPlayer MPCHCAPIPlayer = DummyPlayer
try:
from syncplay.players.mpcbe import MpcBePlayer
except ImportError:
from syncplay.players.basePlayer import DummyPlayer
MpcBePlayer = DummyPlayer
def getAvailablePlayers(): def getAvailablePlayers():
return [MPCHCAPIPlayer, MplayerPlayer, MpvPlayer, VlcPlayer] return [MPCHCAPIPlayer, MplayerPlayer, MpvPlayer, VlcPlayer, MpcBePlayer]

View File

@ -327,6 +327,10 @@ class MPCHCAPIPlayer(BasePlayer):
self.__versionUpdate = threading.Event() self.__versionUpdate = threading.Event()
self.__fileUpdate = threading.RLock() self.__fileUpdate = threading.RLock()
self.__versionUpdate.clear() self.__versionUpdate.clear()
@staticmethod
def getMinVersionErrorMessage():
return getMessage("mpc-version-insufficient-error").format(constants.MPC_MIN_VER)
def drop(self): def drop(self):
self.__preventAsking.set() self.__preventAsking.set()
@ -365,7 +369,7 @@ class MPCHCAPIPlayer(BasePlayer):
def __dropIfNotSufficientVersion(self): def __dropIfNotSufficientVersion(self):
self._mpcApi.askForVersion() self._mpcApi.askForVersion()
if not self.__versionUpdate.wait(0.1) or not self._mpcApi.version: if not self.__versionUpdate.wait(0.1) or not self._mpcApi.version:
self.reactor.callFromThread(self.__client.ui.showErrorMessage, getMessage("mpc-version-insufficient-error").format(constants.MPC_MIN_VER), True) self.reactor.callFromThread(self.__client.ui.showErrorMessage, self.getMinVersionErrorMessage(), True)
self.reactor.callFromThread(self.__client.stop, True) self.reactor.callFromThread(self.__client.stop, True)
def __testMpcReady(self): def __testMpcReady(self):
@ -382,7 +386,7 @@ class MPCHCAPIPlayer(BasePlayer):
self.reactor.callFromThread(self.__client.ui.showErrorMessage, err.message, True) self.reactor.callFromThread(self.__client.ui.showErrorMessage, err.message, True)
self.reactor.callFromThread(self.__client.stop) self.reactor.callFromThread(self.__client.stop)
def initPlayer(self, filePath): def initPlayer(self, filePath):
self.__dropIfNotSufficientVersion() self.__dropIfNotSufficientVersion()
if not self._mpcApi.version: if not self._mpcApi.version:
return return

50
syncplay/players/mpcbe.py Normal file
View File

@ -0,0 +1,50 @@
from syncplay import constants
import os.path
from syncplay.messages import getMessage
from syncplay.players.mpc import MPCHCAPIPlayer
class MpcBePlayer(MPCHCAPIPlayer):
@staticmethod
def run(client, playerPath, filePath, args):
args.extend(['/open', '/new'])
mpc = MpcBePlayer(client)
mpc._mpcApi.callbacks.onConnected = lambda: mpc.initPlayer(filePath if filePath else None)
mpc._mpcApi.startMpc(MpcBePlayer.getExpandedPath(playerPath), args)
client.initPlayer(mpc)
return mpc
@staticmethod
def getDefaultPlayerPathsList():
return constants.MPC_BE_PATHS
@staticmethod
def getIconPath(path):
return constants.MPC_BE_ICONPATH
@staticmethod
def isValidPlayerPath(path):
if MpcBePlayer.getExpandedPath(path):
return True
return False
@staticmethod
def getExpandedPath(path):
if os.path.isfile(path):
if path.lower().endswith(u'mpc-be.exe'.lower()) or path.lower().endswith(u'mpc-be64.exe'.lower()):
return path
if os.path.isfile(path + u"mpc-be.exe"):
path += u"mpc-be.exe"
return path
if os.path.isfile(path + u"\\mpc-be.exe"):
path += u"\\mpc-be.exe"
return path
if os.path.isfile(path + u"mpc-be64.exe"):
path += u"mpc-be64.exe"
return path
if os.path.isfile(path + u"\\mpc-be64.exe"):
path += u"\\mpc-be64.exe"
return path
@staticmethod
def getMinVersionErrorMessage():
return getMessage("mpc-be-version-insufficient-error").format(constants.MPC_BE_MIN_VER)

View File

@ -6,6 +6,7 @@ from syncplay.players.basePlayer import BasePlayer
from syncplay import constants, utils from syncplay import constants, utils
from syncplay.messages import getMessage from syncplay.messages import getMessage
import os, sys import os, sys
from syncplay.utils import isWindows
class MplayerPlayer(BasePlayer): class MplayerPlayer(BasePlayer):
speedSupported = True speedSupported = True
@ -282,7 +283,7 @@ class MplayerPlayer(BasePlayer):
call = [playerPath] call = [playerPath]
if filePath: if filePath:
if sys.platform.startswith('win') and not utils.isASCII(filePath): if isWindows() and not utils.isASCII(filePath):
self.__playerController.delayedFilePath = filePath self.__playerController.delayedFilePath = filePath
filePath = None filePath = None
else: else:

View File

@ -11,6 +11,7 @@ import asynchat, asyncore
import urllib import urllib
import time import time
from syncplay.messages import getMessage from syncplay.messages import getMessage
from syncplay.utils import isBSD, isLinux, isWindows, isMacOS
class VlcPlayer(BasePlayer): class VlcPlayer(BasePlayer):
speedSupported = True speedSupported = True
@ -20,10 +21,10 @@ class VlcPlayer(BasePlayer):
RE_ANSWER = re.compile(constants.VLC_ANSWER_REGEX) RE_ANSWER = re.compile(constants.VLC_ANSWER_REGEX)
SLAVE_ARGS = constants.VLC_SLAVE_ARGS SLAVE_ARGS = constants.VLC_SLAVE_ARGS
if sys.platform.startswith('darwin'): if isMacOS():
SLAVE_ARGS.extend(constants.VLC_SLAVE_OSX_ARGS) SLAVE_ARGS.extend(constants.VLC_SLAVE_MACOS_ARGS)
else: else:
SLAVE_ARGS.extend(constants.VLC_SLAVE_NONOSX_ARGS) SLAVE_ARGS.extend(constants.VLC_SLAVE_NONMACOS_ARGS)
vlcport = random.randrange(constants.VLC_MIN_PORT, constants.VLC_MAX_PORT) if (constants.VLC_MIN_PORT < constants.VLC_MAX_PORT) else constants.VLC_MIN_PORT vlcport = random.randrange(constants.VLC_MIN_PORT, constants.VLC_MAX_PORT) if (constants.VLC_MIN_PORT < constants.VLC_MAX_PORT) else constants.VLC_MIN_PORT
def __init__(self, client, playerPath, filePath, args): def __init__(self, client, playerPath, filePath, args):
@ -146,7 +147,7 @@ class VlcPlayer(BasePlayer):
fileURL = fileURL.replace(u'\\', u'/') fileURL = fileURL.replace(u'\\', u'/')
fileURL = fileURL.encode('utf8') fileURL = fileURL.encode('utf8')
fileURL = urllib.quote_plus(fileURL) fileURL = urllib.quote_plus(fileURL)
if sys.platform.startswith('win'): if isWindows():
fileURL = "file:///" + fileURL fileURL = "file:///" + fileURL
else: else:
fileURL = "file://" + fileURL fileURL = "file://" + fileURL
@ -331,13 +332,13 @@ class VlcPlayer(BasePlayer):
return False return False
playerController._client.ui.showErrorMessage(getMessage("vlc-interface-not-installed")) playerController._client.ui.showErrorMessage(getMessage("vlc-interface-not-installed"))
return False return False
if sys.platform.startswith('linux'): if isLinux():
playerController.vlcIntfPath = "/usr/lib/vlc/lua/intf/" playerController.vlcIntfPath = "/usr/lib/vlc/lua/intf/"
playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), ".local/share/vlc/lua/intf/") playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), ".local/share/vlc/lua/intf/")
elif sys.platform.startswith('darwin'): elif isMacOS():
playerController.vlcIntfPath = "/Applications/VLC.app/Contents/MacOS/share/lua/intf/" playerController.vlcIntfPath = "/Applications/VLC.app/Contents/MacOS/share/lua/intf/"
playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), "Library/Application Support/org.videolan.vlc/lua/intf/") playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), "Library/Application Support/org.videolan.vlc/lua/intf/")
elif 'bsd' in sys.platform or sys.platform.startswith('dragonfly'): elif isBSD():
# *BSD ports/pkgs install to /usr/local by default. # *BSD ports/pkgs install to /usr/local by default.
# This should also work for all the other BSDs, such as OpenBSD or DragonFly. # This should also work for all the other BSDs, such as OpenBSD or DragonFly.
playerController.vlcIntfPath = "/usr/local/lib/vlc/lua/intf/" playerController.vlcIntfPath = "/usr/local/lib/vlc/lua/intf/"
@ -349,7 +350,7 @@ class VlcPlayer(BasePlayer):
if _usevlcintf(playerController.vlcIntfPath, playerController.vlcIntfUserPath): if _usevlcintf(playerController.vlcIntfPath, playerController.vlcIntfUserPath):
playerController.SLAVE_ARGS.append('--lua-config=syncplay={{port=\"{}\"}}'.format(str(playerController.vlcport))) playerController.SLAVE_ARGS.append('--lua-config=syncplay={{port=\"{}\"}}'.format(str(playerController.vlcport)))
else: else:
if sys.platform.startswith('linux'): if isLinux():
playerController.vlcDataPath = "/usr/lib/syncplay/resources" playerController.vlcDataPath = "/usr/lib/syncplay/resources"
else: else:
playerController.vlcDataPath = utils.findWorkingDir() + "\\resources" playerController.vlcDataPath = utils.findWorkingDir() + "\\resources"
@ -387,7 +388,7 @@ class VlcPlayer(BasePlayer):
playerController._client.ui.showErrorMessage( playerController._client.ui.showErrorMessage(
getMessage("media-player-error").format(line), True) getMessage("media-player-error").format(line), True)
break break
if not sys.platform.startswith('darwin'): if not isMacOS():
self.__process.stderr = None self.__process.stderr = None
else: else:
vlcoutputthread = threading.Thread(target = self.handle_vlcoutput, args=()) vlcoutputthread = threading.Thread(target = self.handle_vlcoutput, args=())
@ -401,7 +402,7 @@ class VlcPlayer(BasePlayer):
self._sendingData = threading.Lock() self._sendingData = threading.Lock()
def _shouldListenForSTDOUT(self): def _shouldListenForSTDOUT(self):
if sys.platform.startswith('win'): if isWindows():
return False # Due to VLC3 not using STDOUT/STDERR return False # Due to VLC3 not using STDOUT/STDERR
else: else:
return True return True

View File

@ -6,6 +6,7 @@ import ast
from syncplay import constants, utils, version, milestone from syncplay import constants, utils, version, milestone
from syncplay.messages import getMessage, setLanguage, isValidLanguage from syncplay.messages import getMessage, setLanguage, isValidLanguage
from syncplay.players.playerFactory import PlayerFactory from syncplay.players.playerFactory import PlayerFactory
from syncplay.utils import isMacOS
import codecs import codecs
class InvalidConfigValue(Exception): class InvalidConfigValue(Exception):
@ -411,7 +412,7 @@ class ConfigurationGetter(object):
if QCoreApplication.instance() is None: if QCoreApplication.instance() is None:
self.app = QtWidgets.QApplication(sys.argv) self.app = QtWidgets.QApplication(sys.argv)
qt5reactor.install() qt5reactor.install()
if sys.platform.startswith('darwin'): if isMacOS():
import appnope import appnope
appnope.nope() appnope.nope()
except ImportError: except ImportError:

View File

@ -12,7 +12,8 @@ import sys
import threading import threading
from syncplay.messages import getMessage, getLanguages, setLanguage, getInitialLanguage from syncplay.messages import getMessage, getLanguages, setLanguage, getInitialLanguage
from syncplay import constants from syncplay import constants
from syncplay.utils import isBSD, isLinux, isMacOS
from syncplay.utils import resourcespath, posixresourcespath
class GuiConfiguration: class GuiConfiguration:
def __init__(self, config, error=None, defaultConfig=None): def __init__(self, config, error=None, defaultConfig=None):
self.defaultConfig = defaultConfig self.defaultConfig = defaultConfig
@ -185,12 +186,12 @@ class ConfigDialog(QtWidgets.QDialog):
def _updateExecutableIcon(self, iconpath, playerpath): def _updateExecutableIcon(self, iconpath, playerpath):
if iconpath is not None and iconpath != "": if iconpath is not None and iconpath != "":
if iconpath.endswith('.mng'): if iconpath.endswith('.mng'):
movie = QtGui.QMovie(self.resourcespath + iconpath) movie = QtGui.QMovie(resourcespath + iconpath)
movie.setCacheMode(QtGui.QMovie.CacheMode.CacheAll) movie.setCacheMode(QtGui.QMovie.CacheMode.CacheAll)
self.executableiconLabel.setMovie(movie) self.executableiconLabel.setMovie(movie)
movie.start() movie.start()
else: else:
self.executableiconImage.load(self.resourcespath + iconpath) self.executableiconImage.load(resourcespath + iconpath)
self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(self.executableiconImage)) self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(self.executableiconImage))
else: else:
self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage())) self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage()))
@ -238,11 +239,11 @@ class ConfigDialog(QtWidgets.QDialog):
defaultdirectory = os.environ["ProgramFiles"] defaultdirectory = os.environ["ProgramFiles"]
elif "PROGRAMW6432" in os.environ: elif "PROGRAMW6432" in os.environ:
defaultdirectory = os.environ["ProgramW6432"] defaultdirectory = os.environ["ProgramW6432"]
elif sys.platform.startswith('linux'): elif isLinux():
defaultdirectory = "/usr/bin" defaultdirectory = "/usr/bin"
elif sys.platform.startswith('darwin'): elif isMacOS():
defaultdirectory = "/Applications/" defaultdirectory = "/Applications/"
elif "bsd" in sys.platform or sys.platform.startswith('dragonfly'): elif isBSD():
defaultdirectory = "/usr/local/bin" defaultdirectory = "/usr/local/bin"
fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(self, fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(self,
@ -250,7 +251,7 @@ class ConfigDialog(QtWidgets.QDialog):
defaultdirectory, defaultdirectory,
browserfilter, "", options) browserfilter, "", options)
if fileName: if fileName:
if sys.platform.startswith('darwin') and fileName.endswith('.app'): # see GitHub issue #91 if isMacOS() and fileName.endswith('.app'): # see GitHub issue #91
# Mac OS X application bundles contain a Info.plist in the Contents subdirectory of the .app. # Mac OS X application bundles contain a Info.plist in the Contents subdirectory of the .app.
# This plist file includes the 'CFBundleExecutable' key, which specifies the name of the # This plist file includes the 'CFBundleExecutable' key, which specifies the name of the
# executable. I would have used plistlib here, but since the version of this library in # executable. I would have used plistlib here, but since the version of this library in
@ -530,7 +531,6 @@ class ConfigDialog(QtWidgets.QDialog):
def addBasicTab(self): def addBasicTab(self):
config = self.config config = self.config
playerpaths = self.playerpaths playerpaths = self.playerpaths
resourcespath = self.resourcespath
error = self.error error = self.error
if self.datacleared == True: if self.datacleared == True:
error = constants.ERROR_MESSAGE_MARKER + "{}".format(getMessage("gui-data-cleared-notification")) error = constants.ERROR_MESSAGE_MARKER + "{}".format(getMessage("gui-data-cleared-notification"))
@ -701,22 +701,22 @@ class ConfigDialog(QtWidgets.QDialog):
self.readyUnpauseButtonGroup = QButtonGroup() self.readyUnpauseButtonGroup = QButtonGroup()
self.unpauseIfAlreadyReadyOption = QRadioButton(getMessage("unpause-ifalreadyready-option")) self.unpauseIfAlreadyReadyOption = QRadioButton(getMessage("unpause-ifalreadyready-option"))
self.readyUnpauseButtonGroup.addButton(self.unpauseIfAlreadyReadyOption) self.readyUnpauseButtonGroup.addButton(self.unpauseIfAlreadyReadyOption)
self.unpauseIfAlreadyReadyOption.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.unpauseIfAlreadyReadyOption.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + "chevrons_right.png"))
self.unpauseIfAlreadyReadyOption.setObjectName("unpause-ifalreadyready" + constants.CONFIG_NAME_MARKER + "unpauseAction" + constants.CONFIG_VALUE_MARKER + constants.UNPAUSE_IFALREADYREADY_MODE) self.unpauseIfAlreadyReadyOption.setObjectName("unpause-ifalreadyready" + constants.CONFIG_NAME_MARKER + "unpauseAction" + constants.CONFIG_VALUE_MARKER + constants.UNPAUSE_IFALREADYREADY_MODE)
self.readyUnpauseLayout.addWidget(self.unpauseIfAlreadyReadyOption) self.readyUnpauseLayout.addWidget(self.unpauseIfAlreadyReadyOption)
self.unpauseIfOthersReadyOption = QRadioButton(getMessage("unpause-ifothersready-option")) self.unpauseIfOthersReadyOption = QRadioButton(getMessage("unpause-ifothersready-option"))
self.readyUnpauseButtonGroup.addButton(self.unpauseIfOthersReadyOption) self.readyUnpauseButtonGroup.addButton(self.unpauseIfOthersReadyOption)
self.unpauseIfOthersReadyOption.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.unpauseIfOthersReadyOption.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + "chevrons_right.png"))
self.unpauseIfOthersReadyOption.setObjectName("unpause-ifothersready" + constants.CONFIG_NAME_MARKER + "unpauseAction" + constants.CONFIG_VALUE_MARKER + constants.UNPAUSE_IFOTHERSREADY_MODE) self.unpauseIfOthersReadyOption.setObjectName("unpause-ifothersready" + constants.CONFIG_NAME_MARKER + "unpauseAction" + constants.CONFIG_VALUE_MARKER + constants.UNPAUSE_IFOTHERSREADY_MODE)
self.readyUnpauseLayout.addWidget(self.unpauseIfOthersReadyOption) self.readyUnpauseLayout.addWidget(self.unpauseIfOthersReadyOption)
self.unpauseIfMinUsersReadyOption = QRadioButton(getMessage("unpause-ifminusersready-option")) self.unpauseIfMinUsersReadyOption = QRadioButton(getMessage("unpause-ifminusersready-option"))
self.readyUnpauseButtonGroup.addButton(self.unpauseIfMinUsersReadyOption) self.readyUnpauseButtonGroup.addButton(self.unpauseIfMinUsersReadyOption)
self.unpauseIfMinUsersReadyOption.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.unpauseIfMinUsersReadyOption.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + "chevrons_right.png"))
self.unpauseIfMinUsersReadyOption.setObjectName("unpause-ifminusersready" + constants.CONFIG_NAME_MARKER + "unpauseAction" + constants.CONFIG_VALUE_MARKER + constants.UNPAUSE_IFMINUSERSREADY_MODE) self.unpauseIfMinUsersReadyOption.setObjectName("unpause-ifminusersready" + constants.CONFIG_NAME_MARKER + "unpauseAction" + constants.CONFIG_VALUE_MARKER + constants.UNPAUSE_IFMINUSERSREADY_MODE)
self.readyUnpauseLayout.addWidget(self.unpauseIfMinUsersReadyOption) self.readyUnpauseLayout.addWidget(self.unpauseIfMinUsersReadyOption)
self.unpauseAlwaysUnpauseOption = QRadioButton(getMessage("unpause-always")) self.unpauseAlwaysUnpauseOption = QRadioButton(getMessage("unpause-always"))
self.readyUnpauseButtonGroup.addButton(self.unpauseAlwaysUnpauseOption) self.readyUnpauseButtonGroup.addButton(self.unpauseAlwaysUnpauseOption)
self.unpauseAlwaysUnpauseOption.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png")) self.unpauseAlwaysUnpauseOption.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + "chevrons_right.png"))
self.unpauseAlwaysUnpauseOption.setObjectName("unpause-always" + constants.CONFIG_NAME_MARKER + "unpauseAction" + constants.CONFIG_VALUE_MARKER + constants.UNPAUSE_ALWAYS_MODE) self.unpauseAlwaysUnpauseOption.setObjectName("unpause-always" + constants.CONFIG_NAME_MARKER + "unpauseAction" + constants.CONFIG_VALUE_MARKER + constants.UNPAUSE_ALWAYS_MODE)
self.readyUnpauseLayout.addWidget(self.unpauseAlwaysUnpauseOption) self.readyUnpauseLayout.addWidget(self.unpauseAlwaysUnpauseOption)
self.readyLayout.addWidget(self.readyUnpauseGroup) self.readyLayout.addWidget(self.readyUnpauseGroup)
@ -885,27 +885,27 @@ class ConfigDialog(QtWidgets.QDialog):
self.showSameRoomOSDCheckbox = QCheckBox(getMessage("showsameroomosd-label")) self.showSameRoomOSDCheckbox = QCheckBox(getMessage("showsameroomosd-label"))
self.showSameRoomOSDCheckbox.setObjectName("showSameRoomOSD") self.showSameRoomOSDCheckbox.setObjectName("showSameRoomOSD")
self.showSameRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png")) self.showSameRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + u"chevrons_right.png"))
self.osdSettingsLayout.addWidget(self.showSameRoomOSDCheckbox) self.osdSettingsLayout.addWidget(self.showSameRoomOSDCheckbox)
self.showNonControllerOSDCheckbox = QCheckBox(getMessage("shownoncontrollerosd-label")) self.showNonControllerOSDCheckbox = QCheckBox(getMessage("shownoncontrollerosd-label"))
self.showNonControllerOSDCheckbox.setObjectName("showNonControllerOSD") self.showNonControllerOSDCheckbox.setObjectName("showNonControllerOSD")
self.showNonControllerOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png")) self.showNonControllerOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + u"chevrons_right.png"))
self.osdSettingsLayout.addWidget(self.showNonControllerOSDCheckbox) self.osdSettingsLayout.addWidget(self.showNonControllerOSDCheckbox)
self.showDifferentRoomOSDCheckbox = QCheckBox(getMessage("showdifferentroomosd-label")) self.showDifferentRoomOSDCheckbox = QCheckBox(getMessage("showdifferentroomosd-label"))
self.showDifferentRoomOSDCheckbox.setObjectName("showDifferentRoomOSD") self.showDifferentRoomOSDCheckbox.setObjectName("showDifferentRoomOSD")
self.showDifferentRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png")) self.showDifferentRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + u"chevrons_right.png"))
self.osdSettingsLayout.addWidget(self.showDifferentRoomOSDCheckbox) self.osdSettingsLayout.addWidget(self.showDifferentRoomOSDCheckbox)
self.slowdownOSDCheckbox = QCheckBox(getMessage("showslowdownosd-label")) self.slowdownOSDCheckbox = QCheckBox(getMessage("showslowdownosd-label"))
self.slowdownOSDCheckbox.setObjectName("showSlowdownOSD") self.slowdownOSDCheckbox.setObjectName("showSlowdownOSD")
self.slowdownOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png")) self.slowdownOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + u"chevrons_right.png"))
self.osdSettingsLayout.addWidget(self.slowdownOSDCheckbox) self.osdSettingsLayout.addWidget(self.slowdownOSDCheckbox)
self.showOSDWarningsCheckbox = QCheckBox(getMessage("showosdwarnings-label")) self.showOSDWarningsCheckbox = QCheckBox(getMessage("showosdwarnings-label"))
self.showOSDWarningsCheckbox.setObjectName("showOSDWarnings") self.showOSDWarningsCheckbox.setObjectName("showOSDWarnings")
self.showOSDWarningsCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png")) self.showOSDWarningsCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + u"chevrons_right.png"))
self.osdSettingsLayout.addWidget(self.showOSDWarningsCheckbox) self.osdSettingsLayout.addWidget(self.showOSDWarningsCheckbox)
self.subitems['showOSD'] = ["showSameRoomOSD", "showDifferentRoomOSD", "showSlowdownOSD", "showOSDWarnings", "showNonControllerOSD"] self.subitems['showOSD'] = ["showSameRoomOSD", "showDifferentRoomOSD", "showSlowdownOSD", "showOSDWarnings", "showNonControllerOSD"]
@ -961,11 +961,10 @@ class ConfigDialog(QtWidgets.QDialog):
def addBottomLayout(self): def addBottomLayout(self):
config = self.config config = self.config
resourcespath = self.resourcespath
self.bottomButtonFrame = QtWidgets.QFrame() self.bottomButtonFrame = QtWidgets.QFrame()
self.bottomButtonLayout = QtWidgets.QHBoxLayout() self.bottomButtonLayout = QtWidgets.QHBoxLayout()
self.helpButton = QtWidgets.QPushButton(QtGui.QIcon(self.resourcespath + u'help.png'), getMessage("help-label")) self.helpButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + u'help.png'), getMessage("help-label"))
self.helpButton.setObjectName("help") self.helpButton.setObjectName("help")
self.helpButton.setMaximumSize(self.helpButton.sizeHint()) self.helpButton.setMaximumSize(self.helpButton.sizeHint())
self.helpButton.pressed.connect(self.openHelp) self.helpButton.pressed.connect(self.openHelp)
@ -1006,11 +1005,11 @@ class ConfigDialog(QtWidgets.QDialog):
self.tabListLayout = QtWidgets.QHBoxLayout() self.tabListLayout = QtWidgets.QHBoxLayout()
self.tabListFrame = QtWidgets.QFrame() self.tabListFrame = QtWidgets.QFrame()
self.tabListWidget = QtWidgets.QListWidget() self.tabListWidget = QtWidgets.QListWidget()
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"house.png"),getMessage("basics-label"))) self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + u"house.png"),getMessage("basics-label")))
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"control_pause_blue.png"),getMessage("readiness-label"))) self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + u"control_pause_blue.png"),getMessage("readiness-label")))
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"film_link.png"),getMessage("sync-label"))) self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + u"film_link.png"),getMessage("sync-label")))
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"comments.png"),getMessage("messages-label"))) self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + u"comments.png"),getMessage("messages-label")))
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"cog.png"),getMessage("misc-label"))) self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + u"cog.png"),getMessage("misc-label")))
self.tabListLayout.addWidget(self.tabListWidget) self.tabListLayout.addWidget(self.tabListWidget)
self.tabListFrame.setLayout(self.tabListLayout) self.tabListFrame.setLayout(self.tabListLayout)
self.tabListFrame.setFixedWidth(self.tabListFrame.minimumSizeHint().width() + constants.TAB_PADDING) self.tabListFrame.setFixedWidth(self.tabListFrame.minimumSizeHint().width() + constants.TAB_PADDING)
@ -1109,12 +1108,6 @@ class ConfigDialog(QtWidgets.QDialog):
self.QtWidgets = QtWidgets self.QtWidgets = QtWidgets
self.QtGui = QtGui self.QtGui = QtGui
self.error = error self.error = error
if sys.platform.startswith('win'):
resourcespath = utils.findWorkingDir() + "\\resources\\"
else:
resourcespath = utils.findWorkingDir() + u"/resources/"
self.posixresourcespath = utils.findWorkingDir().replace(u"\\","/") + u"/resources/"
self.resourcespath = resourcespath
super(ConfigDialog, self).__init__() super(ConfigDialog, self).__init__()

View File

@ -5,16 +5,18 @@ if IsPySide2:
from PySide2.QtCore import QStandardPaths from PySide2.QtCore import QStandardPaths
from syncplay import utils, constants, version, release_number from syncplay import utils, constants, version, release_number
from syncplay.messages import getMessage from syncplay.messages import getMessage
from syncplay.utils import resourcespath
import sys import sys
import time import time
import urllib import urllib
from datetime import datetime from datetime import datetime
from syncplay.utils import isLinux, isWindows, isMacOS
import re import re
import os import os
from syncplay.utils import formatTime, sameFilename, sameFilesize, sameFileduration, RoomPasswordProvider, formatSize, isURL from syncplay.utils import formatTime, sameFilename, sameFilesize, sameFileduration, RoomPasswordProvider, formatSize, isURL
from functools import wraps from functools import wraps
from twisted.internet import task from twisted.internet import task
if sys.platform.startswith('darwin') and IsPySide: if isMacOS() and IsPySide:
from Foundation import NSURL from Foundation import NSURL
lastCheckedForUpdates = None lastCheckedForUpdates = None
@ -34,10 +36,6 @@ class UserlistItemDelegate(QtWidgets.QStyledItemDelegate):
if column == constants.USERLIST_GUI_USERNAME_COLUMN: if column == constants.USERLIST_GUI_USERNAME_COLUMN:
currentQAbstractItemModel = indexQModelIndex.model() currentQAbstractItemModel = indexQModelIndex.model()
itemQModelIndex = currentQAbstractItemModel.index(indexQModelIndex.row(), constants.USERLIST_GUI_USERNAME_COLUMN, indexQModelIndex.parent()) itemQModelIndex = currentQAbstractItemModel.index(indexQModelIndex.row(), constants.USERLIST_GUI_USERNAME_COLUMN, indexQModelIndex.parent())
if sys.platform.startswith('win'):
resourcespath = utils.findWorkingDir() + u"\\resources\\"
else:
resourcespath = utils.findWorkingDir() + u"/resources/"
controlIconQPixmap = QtGui.QPixmap(resourcespath + u"user_key.png") controlIconQPixmap = QtGui.QPixmap(resourcespath + u"user_key.png")
tickIconQPixmap = QtGui.QPixmap(resourcespath + u"tick.png") tickIconQPixmap = QtGui.QPixmap(resourcespath + u"tick.png")
crossIconQPixmap = QtGui.QPixmap(resourcespath + u"cross.png") crossIconQPixmap = QtGui.QPixmap(resourcespath + u"cross.png")
@ -65,10 +63,6 @@ class UserlistItemDelegate(QtWidgets.QStyledItemDelegate):
if isUserRow: if isUserRow:
optionQStyleOptionViewItem.rect.setX(optionQStyleOptionViewItem.rect.x()+constants.USERLIST_GUI_USERNAME_OFFSET) optionQStyleOptionViewItem.rect.setX(optionQStyleOptionViewItem.rect.x()+constants.USERLIST_GUI_USERNAME_OFFSET)
if column == constants.USERLIST_GUI_FILENAME_COLUMN: if column == constants.USERLIST_GUI_FILENAME_COLUMN:
if sys.platform.startswith('win'):
resourcespath = utils.findWorkingDir() + u"\\resources\\"
else:
resourcespath = utils.findWorkingDir() + u"/resources/"
currentQAbstractItemModel = indexQModelIndex.model() currentQAbstractItemModel = indexQModelIndex.model()
itemQModelIndex = currentQAbstractItemModel.index(indexQModelIndex.row(), constants.USERLIST_GUI_FILENAME_COLUMN, indexQModelIndex.parent()) itemQModelIndex = currentQAbstractItemModel.index(indexQModelIndex.row(), constants.USERLIST_GUI_FILENAME_COLUMN, indexQModelIndex.parent())
fileSwitchRole = currentQAbstractItemModel.data(itemQModelIndex, Qt.UserRole + constants.FILEITEM_SWITCH_ROLE) fileSwitchRole = currentQAbstractItemModel.data(itemQModelIndex, Qt.UserRole + constants.FILEITEM_SWITCH_ROLE)
@ -90,18 +84,14 @@ class UserlistItemDelegate(QtWidgets.QStyledItemDelegate):
QtWidgets.QStyledItemDelegate.paint(self, itemQPainter, optionQStyleOptionViewItem, indexQModelIndex) QtWidgets.QStyledItemDelegate.paint(self, itemQPainter, optionQStyleOptionViewItem, indexQModelIndex)
class AboutDialog(QtWidgets.QDialog): class AboutDialog(QtWidgets.QDialog):
if sys.platform.startswith('win'):
resourcespath = utils.findWorkingDir() + u"\\resources\\"
else:
resourcespath = utils.findWorkingDir() + u"/resources/"
def __init__(self, parent=None): def __init__(self, parent=None):
super(AboutDialog, self).__init__(parent) super(AboutDialog, self).__init__(parent)
if sys.platform.startswith('darwin'): if isMacOS():
self.setWindowTitle("") self.setWindowTitle("")
else: else:
self.setWindowTitle(getMessage("about-dialog-title")) self.setWindowTitle(getMessage("about-dialog-title"))
if sys.platform.startswith('win'): if isWindows():
self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
nameLabel = QtWidgets.QLabel("<center><strong>Syncplay</strong></center>") nameLabel = QtWidgets.QLabel("<center><strong>Syncplay</strong></center>")
nameLabel.setFont(QtGui.QFont("Helvetica", 20)) nameLabel.setFont(QtGui.QFont("Helvetica", 20))
@ -109,7 +99,7 @@ class AboutDialog(QtWidgets.QDialog):
linkLabel.setOpenExternalLinks(True) linkLabel.setOpenExternalLinks(True)
versionLabel = QtWidgets.QLabel("<center>" + getMessage("about-dialog-release").format(version, release_number, __binding__) + "</center>") versionLabel = QtWidgets.QLabel("<center>" + getMessage("about-dialog-release").format(version, release_number, __binding__) + "</center>")
licenseLabel = QtWidgets.QLabel("<center><p>Copyright &copy; 2017 Syncplay</p><p>" + getMessage("about-dialog-license-text") + "</p></center>") licenseLabel = QtWidgets.QLabel("<center><p>Copyright &copy; 2017 Syncplay</p><p>" + getMessage("about-dialog-license-text") + "</p></center>")
aboutIconPixmap = QtGui.QPixmap(self.resourcespath + u"syncplay.png") aboutIconPixmap = QtGui.QPixmap(resourcespath + u"syncplay.png")
aboutIconLabel = QtWidgets.QLabel() aboutIconLabel = QtWidgets.QLabel()
aboutIconLabel.setPixmap(aboutIconPixmap.scaled(120, 120, Qt.KeepAspectRatio)) aboutIconLabel.setPixmap(aboutIconPixmap.scaled(120, 120, Qt.KeepAspectRatio))
aboutLayout = QtWidgets.QGridLayout() aboutLayout = QtWidgets.QGridLayout()
@ -131,16 +121,16 @@ class AboutDialog(QtWidgets.QDialog):
self.setLayout(aboutLayout) self.setLayout(aboutLayout)
def openLicense(self): def openLicense(self):
if sys.platform.startswith('win'): if isWindows():
QtGui.QDesktopServices.openUrl(QUrl("file:///" + self.resourcespath + u"license.rtf")) QtGui.QDesktopServices.openUrl(QUrl("file:///" + resourcespath + u"license.rtf"))
else: else:
QtGui.QDesktopServices.openUrl(QUrl("file://" + self.resourcespath + u"license.rtf")) QtGui.QDesktopServices.openUrl(QUrl("file://" + resourcespath + u"license.rtf"))
def openDependencies(self): def openDependencies(self):
if sys.platform.startswith('win'): if isWindows():
QtGui.QDesktopServices.openUrl(QUrl("file:///" + self.resourcespath + u"third-party-notices.rtf")) QtGui.QDesktopServices.openUrl(QUrl("file:///" + resourcespath + u"third-party-notices.rtf"))
else: else:
QtGui.QDesktopServices.openUrl(QUrl("file://" + self.resourcespath + u"third-party-notices.rtf")) QtGui.QDesktopServices.openUrl(QUrl("file://" + resourcespath + u"third-party-notices.rtf"))
class MainWindow(QtWidgets.QMainWindow): class MainWindow(QtWidgets.QMainWindow):
insertPosition = None insertPosition = None
@ -160,10 +150,6 @@ class MainWindow(QtWidgets.QMainWindow):
itemQPainter.save() itemQPainter.save()
currentQAbstractItemModel = indexQModelIndex.model() currentQAbstractItemModel = indexQModelIndex.model()
currentlyPlayingFile = currentQAbstractItemModel.data(indexQModelIndex, Qt.UserRole + constants.PLAYLISTITEM_CURRENTLYPLAYING_ROLE) currentlyPlayingFile = currentQAbstractItemModel.data(indexQModelIndex, Qt.UserRole + constants.PLAYLISTITEM_CURRENTLYPLAYING_ROLE)
if sys.platform.startswith('win'):
resourcespath = utils.findWorkingDir() + u"\\resources\\"
else:
resourcespath = utils.findWorkingDir() + u"/resources/"
if currentlyPlayingFile: if currentlyPlayingFile:
currentlyplayingIconQPixmap = QtGui.QPixmap(resourcespath + u"bullet_right_grey.png") currentlyplayingIconQPixmap = QtGui.QPixmap(resourcespath + u"bullet_right_grey.png")
midY = int((optionQStyleOptionViewItem.rect.y() + optionQStyleOptionViewItem.rect.bottomLeft().y()) / 2) midY = int((optionQStyleOptionViewItem.rect.y() + optionQStyleOptionViewItem.rect.bottomLeft().y()) / 2)
@ -219,7 +205,7 @@ class MainWindow(QtWidgets.QMainWindow):
indexRow = window.playlist.count() if window.clearedPlaylistNote else 0 indexRow = window.playlist.count() if window.clearedPlaylistNote else 0
for url in urls[::-1]: for url in urls[::-1]:
if sys.platform.startswith('darwin') and IsPySide: if isMacOS() and IsPySide:
dropfilepath = os.path.abspath(NSURL.URLWithString_(str(url.toString())).filePathURL().path()) dropfilepath = os.path.abspath(NSURL.URLWithString_(str(url.toString())).filePathURL().path())
else: else:
dropfilepath = os.path.abspath(unicode(url.toLocalFile())) dropfilepath = os.path.abspath(unicode(url.toLocalFile()))
@ -324,7 +310,7 @@ class MainWindow(QtWidgets.QMainWindow):
if indexRow == -1: if indexRow == -1:
indexRow = window.playlist.count() indexRow = window.playlist.count()
for url in urls[::-1]: for url in urls[::-1]:
if sys.platform.startswith('darwin') and IsPySide: if isMacOS() and IsPySide:
dropfilepath = os.path.abspath(NSURL.URLWithString_(str(url.toString())).filePathURL().path()) dropfilepath = os.path.abspath(NSURL.URLWithString_(str(url.toString())).filePathURL().path())
else: else:
dropfilepath = os.path.abspath(unicode(url.toLocalFile())) dropfilepath = os.path.abspath(unicode(url.toLocalFile()))
@ -473,11 +459,11 @@ class MainWindow(QtWidgets.QMainWindow):
if isControlledRoom: if isControlledRoom:
if room == currentUser.room and currentUser.isController(): if room == currentUser.room and currentUser.isController():
roomitem.setIcon(QtGui.QPixmap(self.resourcespath + 'lock_open.png')) roomitem.setIcon(QtGui.QPixmap(resourcespath + 'lock_open.png'))
else: else:
roomitem.setIcon(QtGui.QPixmap(self.resourcespath + 'lock.png')) roomitem.setIcon(QtGui.QPixmap(resourcespath + 'lock.png'))
else: else:
roomitem.setIcon(QtGui.QPixmap(self.resourcespath + 'chevrons_right.png')) roomitem.setIcon(QtGui.QPixmap(resourcespath + 'chevrons_right.png'))
for user in rooms[room]: for user in rooms[room]:
useritem = QtGui.QStandardItem(user.username) useritem = QtGui.QStandardItem(user.username)
@ -567,10 +553,6 @@ class MainWindow(QtWidgets.QMainWindow):
@needsClient @needsClient
def openPlaylistMenu(self, position): def openPlaylistMenu(self, position):
indexes = self.playlist.selectedIndexes() indexes = self.playlist.selectedIndexes()
if sys.platform.startswith('win'):
resourcespath = utils.findWorkingDir() + u"\\resources\\"
else:
resourcespath = utils.findWorkingDir() + u"/resources/"
if len(indexes) > 0: if len(indexes) > 0:
item = self.playlist.selectedIndexes()[0] item = self.playlist.selectedIndexes()[0]
else: else:
@ -609,10 +591,6 @@ class MainWindow(QtWidgets.QMainWindow):
def openRoomMenu(self, position): def openRoomMenu(self, position):
# TODO: Deselect items after right click # TODO: Deselect items after right click
indexes = self.listTreeView.selectedIndexes() indexes = self.listTreeView.selectedIndexes()
if sys.platform.startswith('win'):
resourcespath = utils.findWorkingDir() + u"\\resources\\"
else:
resourcespath = utils.findWorkingDir() + u"/resources/"
if len(indexes) > 0: if len(indexes) > 0:
item = self.listTreeView.selectedIndexes()[0] item = self.listTreeView.selectedIndexes()[0]
else: else:
@ -872,7 +850,7 @@ class MainWindow(QtWidgets.QMainWindow):
return return
self.loadMediaBrowseSettings() self.loadMediaBrowseSettings()
if sys.platform.startswith('darwin') and IsPySide: if isMacOS() and IsPySide:
options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.DontUseNativeDialog) options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.DontUseNativeDialog)
else: else:
options = QtWidgets.QFileDialog.Options() options = QtWidgets.QFileDialog.Options()
@ -886,7 +864,7 @@ class MainWindow(QtWidgets.QMainWindow):
fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(self, getMessage("browseformedia-label"), defaultdirectory, fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(self, getMessage("browseformedia-label"), defaultdirectory,
browserfilter, "", options) browserfilter, "", options)
if fileName: if fileName:
if sys.platform.startswith('win'): if isWindows():
fileName = fileName.replace("/", "\\") fileName = fileName.replace("/", "\\")
self.mediadirectory = os.path.dirname(fileName) self.mediadirectory = os.path.dirname(fileName)
self._syncplayClient.fileSwitch.setCurrentDirectory(self.mediadirectory) self._syncplayClient.fileSwitch.setCurrentDirectory(self.mediadirectory)
@ -900,7 +878,7 @@ class MainWindow(QtWidgets.QMainWindow):
return return
self.loadMediaBrowseSettings() self.loadMediaBrowseSettings()
if sys.platform.startswith('darwin') and IsPySide: if isMacOS() and IsPySide:
options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.DontUseNativeDialog) options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.DontUseNativeDialog)
else: else:
options = QtWidgets.QFileDialog.Options() options = QtWidgets.QFileDialog.Options()
@ -916,7 +894,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.updatingPlaylist = True self.updatingPlaylist = True
if fileNames: if fileNames:
for fileName in fileNames: for fileName in fileNames:
if sys.platform.startswith('win'): if isWindows():
fileName = fileName.replace("/", "\\") fileName = fileName.replace("/", "\\")
self.mediadirectory = os.path.dirname(fileName) self.mediadirectory = os.path.dirname(fileName)
self._syncplayClient.fileSwitch.setCurrentDirectory(self.mediadirectory) self._syncplayClient.fileSwitch.setCurrentDirectory(self.mediadirectory)
@ -1051,7 +1029,7 @@ class MainWindow(QtWidgets.QMainWindow):
@needsClient @needsClient
def openAddMediaDirectoryDialog(self, MediaDirectoriesTextbox, MediaDirectoriesDialog): def openAddMediaDirectoryDialog(self, MediaDirectoriesTextbox, MediaDirectoriesDialog):
if sys.platform.startswith('darwin') and IsPySide: if isMacOS() and IsPySide:
options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog) options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog)
else: else:
options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.ShowDirsOnly) options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.ShowDirsOnly)
@ -1121,9 +1099,9 @@ class MainWindow(QtWidgets.QMainWindow):
self.showErrorMessage(getMessage("invalid-offset-value")) self.showErrorMessage(getMessage("invalid-offset-value"))
def openUserGuide(self): def openUserGuide(self):
if sys.platform.startswith('linux'): if isLinux():
self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/linux/")) self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/linux/"))
elif sys.platform.startswith('win'): elif isWindows():
self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/windows/")) self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/windows/"))
else: else:
self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/")) self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/"))
@ -1171,7 +1149,7 @@ class MainWindow(QtWidgets.QMainWindow):
window.chatInput = QtWidgets.QLineEdit() window.chatInput = QtWidgets.QLineEdit()
window.chatInput.setMaxLength(constants.MAX_CHAT_MESSAGE_LENGTH) window.chatInput.setMaxLength(constants.MAX_CHAT_MESSAGE_LENGTH)
window.chatInput.returnPressed.connect(self.sendChatMessage) window.chatInput.returnPressed.connect(self.sendChatMessage)
window.chatButton = QtWidgets.QPushButton(QtGui.QPixmap(self.resourcespath + 'email_go.png'), window.chatButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + 'email_go.png'),
getMessage("sendmessage-label")) getMessage("sendmessage-label"))
window.chatButton.pressed.connect(self.sendChatMessage) window.chatButton.pressed.connect(self.sendChatMessage)
window.chatLayout = QtWidgets.QHBoxLayout() window.chatLayout = QtWidgets.QHBoxLayout()
@ -1226,7 +1204,7 @@ class MainWindow(QtWidgets.QMainWindow):
window.roomInput = QtWidgets.QLineEdit() window.roomInput = QtWidgets.QLineEdit()
window.roomInput.setMaxLength(constants.MAX_ROOM_NAME_LENGTH) window.roomInput.setMaxLength(constants.MAX_ROOM_NAME_LENGTH)
window.roomInput.returnPressed.connect(self.joinRoom) window.roomInput.returnPressed.connect(self.joinRoom)
window.roomButton = QtWidgets.QPushButton(QtGui.QPixmap(self.resourcespath + 'door_in.png'), window.roomButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + 'door_in.png'),
getMessage("joinroom-label")) getMessage("joinroom-label"))
window.roomButton.pressed.connect(self.joinRoom) window.roomButton.pressed.connect(self.joinRoom)
window.roomLayout = QtWidgets.QHBoxLayout() window.roomLayout = QtWidgets.QHBoxLayout()
@ -1348,24 +1326,24 @@ class MainWindow(QtWidgets.QMainWindow):
window.playbackFrame.setLayout(window.playbackLayout) window.playbackFrame.setLayout(window.playbackLayout)
window.seekInput = QtWidgets.QLineEdit() window.seekInput = QtWidgets.QLineEdit()
window.seekInput.returnPressed.connect(self.seekFromButton) window.seekInput.returnPressed.connect(self.seekFromButton)
window.seekButton = QtWidgets.QPushButton(QtGui.QPixmap(self.resourcespath + u'clock_go.png'), "") window.seekButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + u'clock_go.png'), "")
window.seekButton.setToolTip(getMessage("seektime-menu-label")) window.seekButton.setToolTip(getMessage("seektime-menu-label"))
window.seekButton.pressed.connect(self.seekFromButton) window.seekButton.pressed.connect(self.seekFromButton)
window.seekInput.setText("0:00") window.seekInput.setText("0:00")
window.seekInput.setFixedWidth(60) window.seekInput.setFixedWidth(60)
window.playbackLayout.addWidget(window.seekInput) window.playbackLayout.addWidget(window.seekInput)
window.playbackLayout.addWidget(window.seekButton) window.playbackLayout.addWidget(window.seekButton)
window.unseekButton = QtWidgets.QPushButton(QtGui.QPixmap(self.resourcespath + u'arrow_undo.png'), "") window.unseekButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + u'arrow_undo.png'), "")
window.unseekButton.setToolTip(getMessage("undoseek-menu-label")) window.unseekButton.setToolTip(getMessage("undoseek-menu-label"))
window.unseekButton.pressed.connect(self.undoSeek) window.unseekButton.pressed.connect(self.undoSeek)
window.miscLayout = QtWidgets.QHBoxLayout() window.miscLayout = QtWidgets.QHBoxLayout()
window.playbackLayout.addWidget(window.unseekButton) window.playbackLayout.addWidget(window.unseekButton)
window.playButton = QtWidgets.QPushButton(QtGui.QPixmap(self.resourcespath + u'control_play_blue.png'), "") window.playButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + u'control_play_blue.png'), "")
window.playButton.setToolTip(getMessage("play-menu-label")) window.playButton.setToolTip(getMessage("play-menu-label"))
window.playButton.pressed.connect(self.play) window.playButton.pressed.connect(self.play)
window.playbackLayout.addWidget(window.playButton) window.playbackLayout.addWidget(window.playButton)
window.pauseButton = QtWidgets.QPushButton(QtGui.QPixmap(self.resourcespath + 'control_pause_blue.png'), "") window.pauseButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + 'control_pause_blue.png'), "")
window.pauseButton.setToolTip(getMessage("pause-menu-label")) window.pauseButton.setToolTip(getMessage("pause-menu-label"))
window.pauseButton.pressed.connect(self.pause) window.pauseButton.pressed.connect(self.pause)
window.playbackLayout.addWidget(window.pauseButton) window.playbackLayout.addWidget(window.pauseButton)
@ -1379,18 +1357,18 @@ class MainWindow(QtWidgets.QMainWindow):
# File menu # File menu
window.fileMenu = QtWidgets.QMenu(getMessage("file-menu-label"), self) window.fileMenu = QtWidgets.QMenu(getMessage("file-menu-label"), self)
window.openAction = window.fileMenu.addAction(QtGui.QPixmap(self.resourcespath + 'folder_explore.png'), window.openAction = window.fileMenu.addAction(QtGui.QPixmap(resourcespath + 'folder_explore.png'),
getMessage("openmedia-menu-label")) getMessage("openmedia-menu-label"))
window.openAction.triggered.connect(self.browseMediapath) window.openAction.triggered.connect(self.browseMediapath)
window.openAction = window.fileMenu.addAction(QtGui.QPixmap(self.resourcespath + 'world_explore.png'), window.openAction = window.fileMenu.addAction(QtGui.QPixmap(resourcespath + 'world_explore.png'),
getMessage("openstreamurl-menu-label")) getMessage("openstreamurl-menu-label"))
window.openAction.triggered.connect(self.promptForStreamURL) window.openAction.triggered.connect(self.promptForStreamURL)
window.openAction = window.fileMenu.addAction(QtGui.QPixmap(self.resourcespath + 'film_folder_edit.png'), window.openAction = window.fileMenu.addAction(QtGui.QPixmap(resourcespath + 'film_folder_edit.png'),
getMessage("setmediadirectories-menu-label")) getMessage("setmediadirectories-menu-label"))
window.openAction.triggered.connect(self.openSetMediaDirectoriesDialog) window.openAction.triggered.connect(self.openSetMediaDirectoriesDialog)
window.exitAction = window.fileMenu.addAction(QtGui.QPixmap(self.resourcespath + 'cross.png'), window.exitAction = window.fileMenu.addAction(QtGui.QPixmap(resourcespath + 'cross.png'),
getMessage("exit-menu-label")) getMessage("exit-menu-label"))
window.exitAction.triggered.connect(self.exitSyncplay) window.exitAction.triggered.connect(self.exitSyncplay)
window.menuBar.addMenu(window.fileMenu) window.menuBar.addMenu(window.fileMenu)
@ -1398,13 +1376,13 @@ class MainWindow(QtWidgets.QMainWindow):
# Playback menu # Playback menu
window.playbackMenu = QtWidgets.QMenu(getMessage("playback-menu-label"), self) window.playbackMenu = QtWidgets.QMenu(getMessage("playback-menu-label"), self)
window.playAction = window.playbackMenu.addAction(QtGui.QPixmap(self.resourcespath + 'control_play_blue.png'), getMessage("play-menu-label")) window.playAction = window.playbackMenu.addAction(QtGui.QPixmap(resourcespath + 'control_play_blue.png'), getMessage("play-menu-label"))
window.playAction.triggered.connect(self.play) window.playAction.triggered.connect(self.play)
window.pauseAction = window.playbackMenu.addAction(QtGui.QPixmap(self.resourcespath + 'control_pause_blue.png'), getMessage("pause-menu-label")) window.pauseAction = window.playbackMenu.addAction(QtGui.QPixmap(resourcespath + 'control_pause_blue.png'), getMessage("pause-menu-label"))
window.pauseAction.triggered.connect(self.pause) window.pauseAction.triggered.connect(self.pause)
window.seekAction = window.playbackMenu.addAction(QtGui.QPixmap(self.resourcespath + 'clock_go.png'), getMessage("seektime-menu-label")) window.seekAction = window.playbackMenu.addAction(QtGui.QPixmap(resourcespath + 'clock_go.png'), getMessage("seektime-menu-label"))
window.seekAction.triggered.connect(self.seekPositionDialog) window.seekAction.triggered.connect(self.seekPositionDialog)
window.unseekAction = window.playbackMenu.addAction(QtGui.QPixmap(self.resourcespath + 'arrow_undo.png'), getMessage("undoseek-menu-label")) window.unseekAction = window.playbackMenu.addAction(QtGui.QPixmap(resourcespath + 'arrow_undo.png'), getMessage("undoseek-menu-label"))
window.unseekAction.triggered.connect(self.undoSeek) window.unseekAction.triggered.connect(self.undoSeek)
window.menuBar.addMenu(window.playbackMenu) window.menuBar.addMenu(window.playbackMenu)
@ -1412,16 +1390,16 @@ class MainWindow(QtWidgets.QMainWindow):
# Advanced menu # Advanced menu
window.advancedMenu = QtWidgets.QMenu(getMessage("advanced-menu-label"), self) window.advancedMenu = QtWidgets.QMenu(getMessage("advanced-menu-label"), self)
window.setoffsetAction = window.advancedMenu.addAction(QtGui.QPixmap(self.resourcespath + 'timeline_marker.png'), window.setoffsetAction = window.advancedMenu.addAction(QtGui.QPixmap(resourcespath + 'timeline_marker.png'),
getMessage("setoffset-menu-label")) getMessage("setoffset-menu-label"))
window.setoffsetAction.triggered.connect(self.setOffset) window.setoffsetAction.triggered.connect(self.setOffset)
window.setTrustedDomainsAction = window.advancedMenu.addAction(QtGui.QPixmap(self.resourcespath + 'shield_edit.png'), window.setTrustedDomainsAction = window.advancedMenu.addAction(QtGui.QPixmap(resourcespath + 'shield_edit.png'),
getMessage("settrusteddomains-menu-label")) getMessage("settrusteddomains-menu-label"))
window.setTrustedDomainsAction.triggered.connect(self.openSetTrustedDomainsDialog) window.setTrustedDomainsAction.triggered.connect(self.openSetTrustedDomainsDialog)
window.createcontrolledroomAction = window.advancedMenu.addAction( window.createcontrolledroomAction = window.advancedMenu.addAction(
QtGui.QPixmap(self.resourcespath + 'page_white_key.png'), getMessage("createcontrolledroom-menu-label")) QtGui.QPixmap(resourcespath + 'page_white_key.png'), getMessage("createcontrolledroom-menu-label"))
window.createcontrolledroomAction.triggered.connect(self.createControlledRoom) window.createcontrolledroomAction.triggered.connect(self.createControlledRoom)
window.identifyascontroller = window.advancedMenu.addAction(QtGui.QPixmap(self.resourcespath + 'key_go.png'), window.identifyascontroller = window.advancedMenu.addAction(QtGui.QPixmap(resourcespath + 'key_go.png'),
getMessage("identifyascontroller-menu-label")) getMessage("identifyascontroller-menu-label"))
window.identifyascontroller.triggered.connect(self.identifyAsController) window.identifyascontroller.triggered.connect(self.identifyAsController)
@ -1445,23 +1423,23 @@ class MainWindow(QtWidgets.QMainWindow):
window.helpMenu = QtWidgets.QMenu(getMessage("help-menu-label"), self) window.helpMenu = QtWidgets.QMenu(getMessage("help-menu-label"), self)
window.userguideAction = window.helpMenu.addAction(QtGui.QPixmap(self.resourcespath + 'help.png'), window.userguideAction = window.helpMenu.addAction(QtGui.QPixmap(resourcespath + 'help.png'),
getMessage("userguide-menu-label")) getMessage("userguide-menu-label"))
window.userguideAction.triggered.connect(self.openUserGuide) window.userguideAction.triggered.connect(self.openUserGuide)
window.updateAction = window.helpMenu.addAction(QtGui.QPixmap(self.resourcespath + 'application_get.png'), window.updateAction = window.helpMenu.addAction(QtGui.QPixmap(resourcespath + 'application_get.png'),
getMessage("update-menu-label")) getMessage("update-menu-label"))
window.updateAction.triggered.connect(self.userCheckForUpdates) window.updateAction.triggered.connect(self.userCheckForUpdates)
if not sys.platform.startswith('darwin'): if not isMacOS():
window.helpMenu.addSeparator() window.helpMenu.addSeparator()
window.about = window.helpMenu.addAction(QtGui.QPixmap(self.resourcespath + 'syncplay.png'), window.about = window.helpMenu.addAction(QtGui.QPixmap(resourcespath + 'syncplay.png'),
getMessage("about-menu-label")) getMessage("about-menu-label"))
else: else:
window.about = window.helpMenu.addAction("&About") window.about = window.helpMenu.addAction("&About")
window.about.triggered.connect(self.openAbout) window.about.triggered.connect(self.openAbout)
window.menuBar.addMenu(window.helpMenu) window.menuBar.addMenu(window.helpMenu)
if not sys.platform.startswith('darwin'): if not isMacOS():
window.mainLayout.setMenuBar(window.menuBar) window.mainLayout.setMenuBar(window.menuBar)
def openAbout(self): def openAbout(self):
@ -1529,16 +1507,16 @@ class MainWindow(QtWidgets.QMainWindow):
def updateReadyIcon(self): def updateReadyIcon(self):
ready = self.readyPushButton.isChecked() ready = self.readyPushButton.isChecked()
if ready: if ready:
self.readyPushButton.setIcon(QtGui.QPixmap(self.resourcespath + 'tick_checkbox.png')) self.readyPushButton.setIcon(QtGui.QPixmap(resourcespath + 'tick_checkbox.png'))
else: else:
self.readyPushButton.setIcon(QtGui.QPixmap(self.resourcespath + 'empty_checkbox.png')) self.readyPushButton.setIcon(QtGui.QPixmap(resourcespath + 'empty_checkbox.png'))
def updateAutoPlayIcon(self): def updateAutoPlayIcon(self):
ready = self.autoplayPushButton.isChecked() ready = self.autoplayPushButton.isChecked()
if ready: if ready:
self.autoplayPushButton.setIcon(QtGui.QPixmap(self.resourcespath + 'tick_checkbox.png')) self.autoplayPushButton.setIcon(QtGui.QPixmap(resourcespath + 'tick_checkbox.png'))
else: else:
self.autoplayPushButton.setIcon(QtGui.QPixmap(self.resourcespath + 'empty_checkbox.png')) self.autoplayPushButton.setIcon(QtGui.QPixmap(resourcespath + 'empty_checkbox.png'))
def automaticUpdateCheck(self): def automaticUpdateCheck(self):
currentDateTimeValue = QDateTime.currentDateTime() currentDateTimeValue = QDateTime.currentDateTime()
@ -1597,7 +1575,7 @@ class MainWindow(QtWidgets.QMainWindow):
data = event.mimeData() data = event.mimeData()
urls = data.urls() urls = data.urls()
if urls and urls[0].scheme() == 'file': if urls and urls[0].scheme() == 'file':
if sys.platform.startswith('darwin') and IsPySide: if isMacOS() and IsPySide:
dropfilepath = os.path.abspath(NSURL.URLWithString_(str(url.toString())).filePathURL().path()) dropfilepath = os.path.abspath(NSURL.URLWithString_(str(url.toString())).filePathURL().path())
else: else:
dropfilepath = os.path.abspath(unicode(url.toLocalFile())) dropfilepath = os.path.abspath(unicode(url.toLocalFile()))
@ -1732,11 +1710,7 @@ class MainWindow(QtWidgets.QMainWindow):
self._syncplayClient = None self._syncplayClient = None
self.folderSearchEnabled = True self.folderSearchEnabled = True
self.QtGui = QtGui self.QtGui = QtGui
if sys.platform.startswith('win'): if isMacOS():
self.resourcespath = utils.findWorkingDir() + u"\\resources\\"
else:
self.resourcespath = utils.findWorkingDir() + u"/resources/"
if sys.platform.startswith('darwin'):
self.setWindowFlags(self.windowFlags()) self.setWindowFlags(self.windowFlags())
else: else:
self.setWindowFlags(self.windowFlags() & Qt.AA_DontUseNativeMenuBar) self.setWindowFlags(self.windowFlags() & Qt.AA_DontUseNativeMenuBar)
@ -1747,7 +1721,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.addMenubar(self) self.addMenubar(self)
self.addMainFrame(self) self.addMainFrame(self)
self.loadSettings() self.loadSettings()
self.setWindowIcon(QtGui.QPixmap(self.resourcespath + u"syncplay.png")) self.setWindowIcon(QtGui.QPixmap(resourcespath + u"syncplay.png"))
self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & Qt.AA_DontUseNativeMenuBar & Qt.WindowMinimizeButtonHint & ~Qt.WindowContextHelpButtonHint) self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & Qt.AA_DontUseNativeMenuBar & Qt.WindowMinimizeButtonHint & ~Qt.WindowContextHelpButtonHint)
self.show() self.show()
self.setAcceptDrops(True) self.setAcceptDrops(True)

View File

@ -17,6 +17,18 @@ import subprocess
folderSearchEnabled = True folderSearchEnabled = True
def isWindows():
return sys.platform.startswith(constants.OS_WINDOWS)
def isLinux():
return sys.platform.startswith(constants.OS_LINUX)
def isMacOS():
return sys.platform.startswith(constants.OS_MACOS)
def isBSD():
return constants.OS_BSD in sys.platform or sys.platform.startswith(constants.OS_DRAGONFLY)
def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None): def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):
"""Retry calling the decorated function using an exponential backoff. """Retry calling the decorated function using an exponential backoff.
@ -125,11 +137,21 @@ def findWorkingDir():
elif frozen in ('dll', 'console_exe', 'windows_exe'): elif frozen in ('dll', 'console_exe', 'windows_exe'):
path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))) path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
elif frozen in ('macosx_app'): elif frozen in ('macosx_app'):
path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))) path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
else: else:
path = "" path = ""
return path return path
def getResourcesPath():
if isWindows():
return findWorkingDir() + u"\\resources\\"
else:
return findWorkingDir() + u"/resources/"
resourcespath = getResourcesPath()
posixresourcespath = findWorkingDir().replace(u"\\","/") + u"/resources/"
def limitedPowerset(s, minLength): def limitedPowerset(s, minLength):
return itertools.chain.from_iterable(itertools.combinations(s, r) for r in xrange(len(s), minLength, -1)) return itertools.chain.from_iterable(itertools.combinations(s, r) for r in xrange(len(s), minLength, -1))