mirror of
https://github.com/jellyfin/jellyfin-mpv-shim.git
synced 2024-11-22 21:49:41 +00:00
Remove desktop mode.
This commit is contained in:
parent
f0b0c05e0b
commit
929bae24be
@ -41,9 +41,7 @@ Current Dependencies:
|
||||
- `pystray` - Provides systray icon. (Optional)
|
||||
- `tkinter` - Provides GUI for adding servers and viewing logs. (Optional)
|
||||
- `Jinja2` - Renders HTML for display mirroring. (Optional)
|
||||
- `pywebview` - Displays HTML for display mirroring or webclient. (Optional)
|
||||
- `Flask` - Used to serve the webclient in desktop mode. (Optional)
|
||||
- `Werkzeug` - Used to serve the webclient in desktop mode. (Optional)
|
||||
- `pywebview` - Displays HTML for display mirroring. (Optional)
|
||||
- `pypresence` - Used for Discord Rich Presence integration. (Optional)
|
||||
|
||||
## Project Overview
|
||||
@ -78,7 +76,6 @@ Current Dependencies:
|
||||
- `video_profile.py` - Implements support for shader pack option profiles and related menu items.
|
||||
- `win_utils.py` - Implements window management workarounds for Windows.
|
||||
- `display_mirror` - Package that implements the full-screen display mirroring.
|
||||
- `webclient_view` - Package that implements the webclient UI. (The actual webclient is a [separate repo](https://github.com/iwalton3/jellyfin-web).)
|
||||
- `integration` - This contains the appstream metadata, icons, and desktop files used in the Flatpak version.
|
||||
- `default_shader_pack` - This is where the `gen_pkg.sh` script installs the [default-shader-pack](https://github.com/iwalton3/default-shader-pack).
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
; Script generated by the Inno Setup Script Wizard.
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
|
||||
#define MyAppName "Jellyfin Desktop"
|
||||
#define MyAppVersion "1.10.4"
|
||||
#define MyAppName "Jellyfin MPV Shim"
|
||||
#define MyAppVersion "2.0.0"
|
||||
#define MyAppPublisher "Ian Walton"
|
||||
#define MyAppURL "https://github.com/jellyfin/jellyfin-desktop"
|
||||
#define MyAppExeName "run-desktop.exe"
|
||||
#define MyAppURL "https://github.com/jellyfin/jellyfin-mpv-shim"
|
||||
#define MyAppExeName "run.exe"
|
||||
|
||||
[Setup]
|
||||
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
|
||||
@ -25,7 +25,7 @@ LicenseFile=LICENSE.md
|
||||
;PrivilegesRequired=lowest
|
||||
PrivilegesRequiredOverridesAllowed=dialog
|
||||
OutputDir=dist
|
||||
OutputBaseFilename=jellyfin-mpv-desktop_version_installer
|
||||
OutputBaseFilename=jellyfin-mpv-shim_version_installer
|
||||
SetupIconFile=jellyfin.ico
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
@ -38,12 +38,11 @@ Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
|
||||
[Files]
|
||||
Source: "dist\run-desktop\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "dist\run\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
|
||||
[Icons]
|
||||
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||
Name: "{autoprograms}\Jellyfin MPV Shim"; Filename: "{app}\{#MyAppExeName}"; Parameters: "--shim"
|
||||
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
@ -1,6 +1,5 @@
|
||||
include jellyfin_mpv_shim/systray.png
|
||||
recursive-include jellyfin_mpv_shim/webclient_view/webclient *
|
||||
recursive-include jellyfin_mpv_shim/integration *
|
||||
recursive-include jellyfin_mpv_shim/default_shader_pack *
|
||||
recursive-include jellyfin_mpv_shim/messages *.mo
|
||||
include jellyfin_mpv_shim/mouse.lua
|
||||
include jellyfin_mpv_shim/mouse.lua
|
||||
|
106
README.md
106
README.md
@ -1,46 +1,36 @@
|
||||
# Jellyfin Desktop (MPV Shim)
|
||||
# Jellyfin MPV Shim
|
||||
|
||||
[![Current Release](https://img.shields.io/github/release/jellyfin/jellyfin-desktop.svg)](https://github.com/jellyfin/jellyfin-desktop/releases)
|
||||
[![Current Release](https://img.shields.io/github/release/jellyfin/jellyfin-mpv-shim.svg)](https://github.com/jellyfin/jellyfin-mpv-shim/releases)
|
||||
[![PyPI](https://img.shields.io/pypi/v/jellyfin-mpv-shim)](https://pypi.org/project/jellyfin-mpv-shim/)
|
||||
[![Translation Status](https://translate.jellyfin.org/widgets/jellyfin/-/jellyfin-desktop/svg-badge.svg)](https://translate.jellyfin.org/projects/jellyfin/jellyfin-desktop/)
|
||||
[![Build Status](https://dev.azure.com/jellyfin-project/jellyfin/_apis/build/status/jellyfin.jellyfin-desktop?branchName=master)](https://dev.azure.com/jellyfin-project/jellyfin/_build/latest?definitionId=22&branchName=master)
|
||||
[![Translation Status](https://translate.jellyfin.org/widgets/jellyfin/-/jellyfin-mpv-shim/svg-badge.svg)](https://translate.jellyfin.org/projects/jellyfin/jellyfin-mpv-shim/)
|
||||
[![Build Status](https://dev.azure.com/jellyfin-project/jellyfin/_apis/build/status/jellyfin.jellyfin-mpv-shim?branchName=master)](https://dev.azure.com/jellyfin-project/jellyfin/_build/latest?definitionId=22&branchName=master)
|
||||
[![Code Stype](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
|
||||
|
||||
Jellyfin Desktop is a fully featured, cross-platform desktop and cast client for Jellyfin.
|
||||
Jellyfin MPV Shim is a cross-platform cast client for Jellyfin.
|
||||
It has support for all your advanced media files without transcoding, as well as tons of
|
||||
features which set it apart from other multimedia clients:
|
||||
|
||||
- Direct play most media using MPV.
|
||||
- Watch videos with friends using SyncPlay.
|
||||
- Offers both a desktop mode and a shim mode which runs in the background.
|
||||
- Offers a shim mode which runs in the background.
|
||||
- The Jellyfin mobile apps can fully control the client.
|
||||
- [Reconfigure subtitles](https://github.com/jellyfin/jellyfin-desktop#menu) for an entire season at once.
|
||||
- Supports all of the [MPV keyboard shortcuts](https://github.com/jellyfin/jellyfin-desktop#keyboard-shortcuts).
|
||||
- Enhance your video with [Shader Packs](https://github.com/jellyfin/jellyfin-desktop#menu) and [SVP Integration](https://github.com/jellyfin/jellyfin-desktop#svp-integration).
|
||||
- [Reconfigure subtitles](https://github.com/jellyfin/jellyfin-mpv-shim#menu) for an entire season at once.
|
||||
- Supports all of the [MPV keyboard shortcuts](https://github.com/jellyfin/jellyfin-mpv-shim#keyboard-shortcuts).
|
||||
- Enhance your video with [Shader Packs](https://github.com/jellyfin/jellyfin-mpv-shim#menu) and [SVP Integration](https://github.com/jellyfin/jellyfin-mpv-shim#svp-integration).
|
||||
- Optionally share your media activity with friends using Discord Rich Presence.
|
||||
- Most features, as well as MPV itself, [can be extensively configured](https://github.com/jellyfin/jellyfin-desktop#configuration).
|
||||
- You can configure the player to use an [external MPV player](https://github.com/jellyfin/jellyfin-desktop#external-mpv) of your choice.
|
||||
- Enable a chromecast-like experience with [Display Mirroring](https://github.com/jellyfin/jellyfin-desktop#display-mirroring).
|
||||
- You can [trigger commands to run](https://github.com/jellyfin/jellyfin-desktop#shell-command-triggers) when certain events happen.
|
||||
- Most features, as well as MPV itself, [can be extensively configured](https://github.com/jellyfin/jellyfin-mpv-shim#configuration).
|
||||
- You can configure the player to use an [external MPV player](https://github.com/jellyfin/jellyfin-mpv-shim#external-mpv) of your choice.
|
||||
- Enable a chromecast-like experience with [Display Mirroring](https://github.com/jellyfin/jellyfin-mpv-shim#display-mirroring).
|
||||
- You can [trigger commands to run](https://github.com/jellyfin/jellyfin-mpv-shim#shell-command-triggers) when certain events happen.
|
||||
|
||||
To learn more, keep reading. This README explains everything, including [configuration](https://github.com/jellyfin/jellyfin-desktop#configuration), [tips & tricks](https://github.com/jellyfin/jellyfin-desktop#tips-and-tricks), and [development information](https://github.com/jellyfin/jellyfin-desktop#development).
|
||||
To learn more, keep reading. This README explains everything, including [configuration](https://github.com/jellyfin/jellyfin-mpv-shim#configuration), [tips & tricks](https://github.com/jellyfin/jellyfin-mpv-shim#tips-and-tricks), and [development information](https://github.com/jellyfin/jellyfin-mpv-shim#development).
|
||||
|
||||
## Getting Started
|
||||
|
||||
If you are on Windows, simply [download the binary](https://github.com/jellyfin/jellyfin-desktop/releases).
|
||||
If you are using Linux, you can [install via flathub](https://flathub.org/apps/details/com.github.iwalton3.jellyfin-mpv-shim) or [install via pip](https://github.com/jellyfin/jellyfin-desktop/blob/master/README.md#linux-installation). If you are on macOS, see the [macOS Installation](https://github.com/jellyfin/jellyfin-desktop/blob/master/README.md#osx-installation)
|
||||
If you are on Windows, simply [download the binary](https://github.com/jellyfin/jellyfin-mpv-shim/releases).
|
||||
If you are using Linux, you can [install via flathub](https://flathub.org/apps/details/com.github.iwalton3.jellyfin-mpv-shim) or [install via pip](https://github.com/jellyfin/jellyfin-mpv-shim/blob/master/README.md#linux-installation). If you are on macOS, see the [macOS Installation](https://github.com/jellyfin/jellyfin-mpv-shim/blob/master/README.md#osx-installation)
|
||||
section below.
|
||||
|
||||
### Desktop Client
|
||||
|
||||
Launch the client. You should see the Jellyfin web app. Log in to your server and use it as normal.
|
||||
All videos will load in MPV just like MPV Shim.
|
||||
|
||||
Please note: The desktop client for Windows contains significantly more files than MPV Shim, so it
|
||||
is distributed as an installer. It will work without admin rights.
|
||||
|
||||
### MPV Shim
|
||||
|
||||
To use the client, simply launch it and log into your Jellyfin server. You’ll need to enter the
|
||||
URL to your server, for example `http://server_ip:8096` or `https://secure_domain`. Make sure to
|
||||
include the subdirectory and port number if applicable. You can then cast your media
|
||||
@ -64,13 +54,12 @@ bare IP addresses and not specifying the port by default. If you want to connect
|
||||
|
||||
Please also note that the on-screen controller for MPV (if available) cannot change the
|
||||
audio and subtitle track configurations for transcoded media. It also cannot load external
|
||||
subtitles. You must either [use the menu](https://github.com/jellyfin/jellyfin-desktop#menu) or the application you casted from.
|
||||
subtitles. You must either [use the menu](https://github.com/jellyfin/jellyfin-mpv-shim#menu) or the application you casted from.
|
||||
|
||||
Please note the following issues with controlling SyncPlay:
|
||||
- The desktop client can join SyncPlay groups from the web app's menu, but not create them.
|
||||
- If you attempt to join a SyncPlay group when casting to MPV Shim, it will play the media but it will not activate SyncPlay.
|
||||
- You can, however, proceed to activate SyncPlay [using the menu within MPV](https://github.com/jellyfin/jellyfin-desktop#menu).
|
||||
- If you would like to create a group or join a group for currently playing media, [use menu within MPV](https://github.com/jellyfin/jellyfin-desktop#menu).
|
||||
- You can, however, proceed to activate SyncPlay [using the menu within MPV](https://github.com/jellyfin/jellyfin-mpv-shim#menu).
|
||||
- If you would like to create a group or join a group for currently playing media, [use menu within MPV](https://github.com/jellyfin/jellyfin-mpv-shim#menu).
|
||||
- SyncPlay as of 10.7.0 is new and kind of fragile. You may need to rejoin or even restart the client. Please report any issues you find.
|
||||
|
||||
Music playback sort-of works, but repeat, shuffle, and gapless playback have not been implemented and
|
||||
@ -336,22 +325,6 @@ need to.
|
||||
- This could break if you use revert-seek markers or scripts that use it.
|
||||
- `sync_osd_message` - Write syncplay status messages to OSD. Default: `true`
|
||||
|
||||
### Desktop Mode Settings
|
||||
|
||||
These settings pertain to the "Desktop" (embedded webview) mode only.
|
||||
|
||||
- `enable_desktop` - Use the desktop client. Default: `false`
|
||||
- You can also use it by running the `jellyfin-mpv-desktop`.
|
||||
- If you are using the Windows build, you must download the desktop version.
|
||||
- `desktop_fullscreen` - Run the desktop client in fullscreen. Default: `false`
|
||||
- `desktop_keep_loc` - Remember the position of the desktop client. Default: `false`
|
||||
- This has been infamous for causing the window to be positioned off-screen.
|
||||
- If you enable this and that happens, you can delete `layout.json` to fix it.
|
||||
- `desktop_keep_size` - Remember the position of the desktop client. Default: `true`
|
||||
- Set the window size, but not the position. Hopefully won't cause the client to open off-screen.
|
||||
- `desktop_scale` - Allows changing the scale factor for the desktop app. Default: `1.0`
|
||||
- This can be useful if you are on a platform that doesn't support HiDPI very well.
|
||||
|
||||
### Debugging
|
||||
|
||||
These settings assist with debugging. You will often be asked to configure them when reporting an issue.
|
||||
@ -414,7 +387,7 @@ Determine which screen you would like MPV to show up on.
|
||||
- If you are on Windows, right click the desktop and select "Display Settings". Take the monitor number and subtract one.
|
||||
- If you are on Linux, run `xrandr`. The screen number is the number you want. If there is only one proceed to **Option 2**.
|
||||
|
||||
Add the following to your `mpv.conf` in the [config directory](https://github.com/jellyfin/jellyfin-desktop#mpv-configuration), replacing `0` with the number from the previous step:
|
||||
Add the following to your `mpv.conf` in the [config directory](https://github.com/jellyfin/jellyfin-mpv-shim#mpv-configuration), replacing `0` with the number from the previous step:
|
||||
```
|
||||
fs=yes
|
||||
fs-screen=0
|
||||
@ -442,7 +415,7 @@ LVDS-0 connected 1600x900+1920+180 (normal left inverted right x axis y axis) 30
|
||||
1600x900 59.98*+
|
||||
```
|
||||
|
||||
If you want MPV to open on VGA-0 for instance, add the following to your `mpv.conf` in the [config directory](https://github.com/jellyfin/jellyfin-desktop#mpv-configuration):
|
||||
If you want MPV to open on VGA-0 for instance, add the following to your `mpv.conf` in the [config directory](https://github.com/jellyfin/jellyfin-mpv-shim#mpv-configuration):
|
||||
```
|
||||
fs=yes
|
||||
geometry=1920x1080+0+0
|
||||
@ -539,8 +512,7 @@ The project is dependent on `python-mpv`, `python-mpv-jsonipc`, `pydantic`, and
|
||||
using Windows and would like mpv to be maximize properly, `pywin32` is also needed. The GUI
|
||||
component uses `pystray` and `tkinter`, but there is a fallback cli mode. The mirroring dependencies
|
||||
are `Jinja2` and `pywebview`, along with platform-specific dependencies. (See the installation and building
|
||||
guides for details on platform-specific dependencies for display mirroring.) The desktop client depends on
|
||||
`pywebview`, `Flask`, and `Werkzeug`.
|
||||
guides for details on platform-specific dependencies for display mirroring.)
|
||||
|
||||
This project is based Plex MPV Shim, which is based on https://github.com/wnielson/omplex, which
|
||||
is available under the terms of the MIT License. The project was ported to python3, modified to
|
||||
@ -560,14 +532,14 @@ If you are on Windows there are additional dependencies. Please see the Windows
|
||||
|
||||
1. Install the dependencies: `sudo pip3 install --upgrade python-mpv jellyfin-apiclient-python pystray Jinja2 pywebview python-mpv-jsonipc Flask Werkzeug pypresence pydantic`.
|
||||
- If you run `./gen_pkg.sh --install`, it will also fetch these for you.
|
||||
2. Clone this repository: `git clone https://github.com/jellyfin/jellyfin-desktop`
|
||||
2. Clone this repository: `git clone https://github.com/jellyfin/jellyfin-mpv-shim`
|
||||
- You can also download a zip build.
|
||||
3. `cd` to the repository: `cd jellyfin-mpv-shim`
|
||||
4. Run prepare script: `./gen_pkg.sh`
|
||||
- To do this manually, download the web client, shader pack, and build the language files.
|
||||
5. Ensure you have a copy of `libmpv1` or `mpv` available.
|
||||
6. Install any platform-specific dependencies from the respective install tutorials.
|
||||
7. You should now be able to run the program with `./run.py` or `./run-desktop.py`. Installation is possible with `sudo pip3 install .`.
|
||||
7. You should now be able to run the program with `./run.py`. Installation is possible with `sudo pip3 install .`.
|
||||
- You can also install the package with `./gen_pkg.sh --install`.
|
||||
|
||||
### Translation
|
||||
@ -592,13 +564,6 @@ If you are on Linux, you can install via pip. You'll need [libmpv1](https://gith
|
||||
```bash
|
||||
sudo pip3 install --upgrade jellyfin-mpv-shim
|
||||
```
|
||||
If you would like the Desktop client (run with `jellyfin-mpv-desktop`), also install:
|
||||
```
|
||||
sudo apt install python3-flask python3-webview python3-werkzeug
|
||||
# -- OR --
|
||||
sudo pip3 install jellyfin-mpv-shim[desktop]
|
||||
sudo apt install gir1.2-webkit2-4.0
|
||||
```
|
||||
If you would like the GUI and systray features, also install `pystray` and `tkinter`:
|
||||
```bash
|
||||
sudo pip3 install pystray
|
||||
@ -637,13 +602,6 @@ To install the CLI version:
|
||||
3. Install jellyfin-mpv-shim. `pip3 install --upgrade jellyfin-mpv-shim`
|
||||
4. Run `jellyfin-mpv-shim`.
|
||||
|
||||
If you'd like to install the desktop client (currently requires python from brew):
|
||||
|
||||
1. Install brew. ([Instructions](https://brew.sh/))
|
||||
2. Install python3 and mpv. `brew install python mpv`
|
||||
3. Install jellyfin-mpv-shim. `pip3 install --upgrade 'jellyfin-mpv-shim[desktop]'`
|
||||
4. Run `jellyfin-mpv-desktop`.
|
||||
|
||||
If you'd like to install the GUI version, you need a working copy of tkinter.
|
||||
|
||||
1. Install pyenv. ([Instructions](https://medium.com/python-every-day/python-development-on-macos-with-pyenv-2509c694a808))
|
||||
@ -666,19 +624,17 @@ the installer. If you'd like to build a 32 bit version, download the 32 bit vers
|
||||
copy it into a new folder called mpv32. You'll also need [WebBrowserInterop.x86.dll](https://github.com/r0x0r/pywebview/blob/master/webview/lib/WebBrowserInterop.x86.dll?raw=true).
|
||||
You may also need to edit the batch file for 32 bit builds to point to the right python executable.
|
||||
|
||||
1. Install Git for Windows. Open Git Bash and run `git clone https://github.com/jellyfin/jellyfin-desktop; cd jellyfin-desktop`.
|
||||
1. Install Git for Windows. Open Git Bash and run `git clone https://github.com/jellyfin/jellyfin-mpv-shim; cd jellyfin-mpv-shim`.
|
||||
- You can update the project later with `git pull`.
|
||||
2. Install [Python3](https://www.python.org/downloads/) with PATH enabled. Install [7zip](https://ninite.com/7zip/).
|
||||
3. After installing python3, open `cmd` as admin and run `pip install --upgrade pyinstaller python-mpv jellyfin-apiclient-python pywin32 pystray Jinja2 pywebview[cef] python-mpv-jsonipc Flask Werkzeug pypresence pydantic`.
|
||||
3. After installing python3, open `cmd` as admin and run `pip install --upgrade pyinstaller python-mpv jellyfin-apiclient-python pywin32 pystray Jinja2 pywebview python-mpv-jsonipc pypresence pydantic`.
|
||||
- You may need to install pydantic with `SKIP_CYTHON=1 pip install git+https://github.com/samuelcolvin/pydantic.git@v0.32`
|
||||
- Details: https://github.com/pyinstaller/pyinstaller/issues/4346
|
||||
4. Download [libmpv](https://sourceforge.net/projects/mpv-player-windows/files/libmpv/).
|
||||
5. Extract the `mpv-1.dll` from the file and move it to the `jellyfin-mpv-shim` folder.
|
||||
6. Open a regular `cmd` prompt. Navigate to the `jellyfin-mpv-shim` folder.
|
||||
7. (Edge Build, disabled by default) Download [WebBrowserInterop.x64.dll](https://github.com/r0x0r/pywebview/blob/master/webview/lib/WebBrowserInterop.x64.dll?raw=true) and [Winforms Webview](https://www.nuget.org/api/v2/package/Microsoft.Toolkit.Forms.UI.Controls.WebView/6.0.0).
|
||||
8. (Edge Build, disabled by default) Rename the `*.nupkg` to a `*.zip` file and extract `lib\net462\Microsoft.Toolkit.Forms.UI.Controls.WebView.dll` to the project root.
|
||||
9. (CEF Desktop Client) Copy the folder `AppData\Local\Programs\Python\Python37\Lib\site-packages\cefpython3` to `cef\cefpython3`.
|
||||
10. Run `./gen_pkg.sh --skip-build` using the Git for Windows console.
|
||||
- This builds the translation files and downloads the web client and shader packs.
|
||||
11. Remove `libEGL.dll` from `cef\cefpython3`, as it breaks mpv's glsl support. (How CEF works without this is a mystery to me.)
|
||||
12. Run `build-win.bat`.
|
||||
7. Download [WebBrowserInterop.x64.dll](https://github.com/r0x0r/pywebview/blob/master/webview/lib/WebBrowserInterop.x64.dll?raw=true) and [Winforms Webview](https://www.nuget.org/api/v2/package/Microsoft.Toolkit.Forms.UI.Controls.WebView/6.0.0).
|
||||
8. Rename the `*.nupkg` to a `*.zip` file and extract `lib\net462\Microsoft.Toolkit.Forms.UI.Controls.WebView.dll` to the project root.
|
||||
9. Run `./gen_pkg.sh --skip-build` using the Git for Windows console.
|
||||
- This builds the translation files and downloads the shader packs.
|
||||
10. Run `build-win.bat`.
|
||||
|
@ -1,12 +1,12 @@
|
||||
#!/bin/bash
|
||||
mkdir -p publish publish/Shim publish/DesktopInstaller publish/DesktopInstallerLegacy publish/DesktopDebug
|
||||
mkdir -p publish publish/Portable publish/Installer publish/InstallerLegacy publish/Debug
|
||||
version=$(cat jellyfin_mpv_shim/constants.py | grep '^CLIENT_VERSION' | cut -d '"' -f 2)
|
||||
if [[ "$1" == "standard" ]]
|
||||
then
|
||||
cp dist/jellyfin-mpv-desktop_version_installer.exe publish/DesktopInstaller/jellyfin-mpv-desktop_${version}_installer.exe || exit 1
|
||||
cp dist/jellyfin-mpv-shim_version_installer.exe publish/Installer/jellyfin-mpv-shim_${version}_installer.exe || exit 1
|
||||
cp dist/run.exe publish/Shim/jellyfin-mpv-shim_${version}.exe || exit 1
|
||||
mv dist/run-desktop publish/DesktopDebug/ || exit 1
|
||||
mv dist/run publish/Debug/ || exit 1
|
||||
elif [[ "$1" == "legacy" ]]
|
||||
then
|
||||
cp dist/jellyfin-mpv-desktop_version_installer.exe publish/DesktopInstallerLegacy/jellyfin-mpv-desktop_${version}_LEGACY32_installer.exe || exit 1
|
||||
cp dist/jellyfin-mpv-shim_version_installer.exe publish/InstallerLegacy/jellyfin-mpv-shim_${version}_LEGACY32_installer.exe || exit 1
|
||||
fi
|
||||
|
@ -26,9 +26,9 @@ jobs:
|
||||
displayName: Cache pip packages
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: '"bindep 2021-04-13" | "$(Agent.OS)"'
|
||||
key: '"bindep 2021-04-19" | "$(Agent.OS)"'
|
||||
restoreKeys: |
|
||||
"bindep 2021-04-13"
|
||||
"bindep 2021-04-19"
|
||||
path: bindep
|
||||
cacheHitVar: CACHE_RESTORED
|
||||
displayName: Cache binary dependencies
|
||||
@ -61,7 +61,7 @@ jobs:
|
||||
TargetFolder: '.'
|
||||
displayName: Copy Binary Dependencies
|
||||
|
||||
- script: pip install .[all] pywebview[cef]==3.4 pywin32 cefpython3==66.0
|
||||
- script: pip install .[all] pywebview==3.4 pywin32
|
||||
displayName: PIP Dependencies
|
||||
- bash: 'pip uninstall -y pydantic; SKIP_CYTHON=1 pip install --force-reinstall --ignore-installed --no-binary :all: pydantic==0.32'
|
||||
displayName: Pydantic w/o CYTHON
|
||||
@ -76,12 +76,12 @@ jobs:
|
||||
- bash: ./artifacts.sh standard
|
||||
displayName: Main Artifact Rename
|
||||
|
||||
- publish: publish/Shim
|
||||
artifact: ShimPortable
|
||||
- publish: publish/DesktopInstaller
|
||||
artifact: DesktopInstaller
|
||||
- publish: publish/DesktopDebug
|
||||
artifact: DesktopDebug
|
||||
- publish: publish/Portable
|
||||
artifact: Portable
|
||||
- publish: publish/Installer
|
||||
artifact: Installer
|
||||
- publish: publish/Debug
|
||||
artifact: Debug
|
||||
|
||||
- job: LegacyWindows
|
||||
pool:
|
||||
@ -103,9 +103,9 @@ jobs:
|
||||
displayName: Cache pip packages
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: '"bindep 2020-08-22" | "$(Agent.OS)"'
|
||||
key: '"bindep 2021-04-19" | "$(Agent.OS)"'
|
||||
restoreKeys: |
|
||||
"bindep 2020-08-22"
|
||||
"bindep 2021-04-19"
|
||||
path: bindep
|
||||
cacheHitVar: CACHE_RESTORED
|
||||
displayName: Cache binary dependencies
|
||||
@ -138,7 +138,7 @@ jobs:
|
||||
TargetFolder: '.'
|
||||
displayName: Copy Binary Dependencies
|
||||
|
||||
- script: pip install .[all] pywebview[cef]==3.3.3 pywin32
|
||||
- script: pip install .[all] pywebview==3.3.3 pywin32
|
||||
displayName: PIP Dependencies x86
|
||||
- bash: 'pip uninstall -y pydantic; SKIP_CYTHON=1 pip install --force-reinstall --ignore-installed --no-binary :all: pydantic==0.32'
|
||||
displayName: Pydantic w/o CYTHON x86
|
||||
@ -151,5 +151,5 @@ jobs:
|
||||
- bash: ./artifacts.sh legacy
|
||||
displayName: Legacy Artifact Rename
|
||||
|
||||
- publish: publish/DesktopInstallerLegacy
|
||||
artifact: DesktopInstallerLegacy
|
||||
- publish: publish/InstallerLegacy
|
||||
artifact: InstallerLegacy
|
||||
|
@ -1,20 +1,8 @@
|
||||
@echo off
|
||||
rd /s /q __pycache__ dist build
|
||||
set PATH=%PATH%;%CD%
|
||||
|
||||
rem ATTENTION: This file is broken. PyInstaller still packages the 64 bit version of libmpv for some reason.
|
||||
rem The desktop version (and corresponding shim shortcut) do work, however.
|
||||
|
||||
rem Edge-based build
|
||||
rem "C:\Program Files (x86)\Python37-32\Scripts\pyinstaller" -w --add-binary "mpv32\mpv-1.dll;." --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\webclient_view\webclient;jellyfin_mpv_shim\webclient_view\webclient" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --icon jellyfin.ico run-desktop-edge.py
|
||||
rem CEF-based build
|
||||
pyinstaller -w --add-binary "mpv32\mpv-1.dll;." --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --hidden-import pystray._win32 --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\webclient_view\webclient;jellyfin_mpv_shim\webclient_view\webclient" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --icon jellyfin.ico run-desktop.py
|
||||
pyinstaller -w --add-binary "mpv32\mpv-1.dll;." --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --hidden-import pystray._win32 --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --icon jellyfin.ico run.py
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
xcopy /E /Y cef32\cefpython3 dist\run-desktop\
|
||||
xcopy /E /Y mpv32\mpv-1.dll dist\run-desktop\
|
||||
del dist\run-desktop\run-desktop.exe.manifest
|
||||
copy hidpi.manifest dist\run-desktop\run-desktop.exe.manifest
|
||||
rem rd /s /q __pycache__ build
|
||||
rem "C:\Program Files (x86)\Python37-32\Scripts\pyinstaller" -wF --add-binary "mpv32\mpv-1.dll;." --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --exclude-module cefpython3 --icon jellyfin.ico run.py
|
||||
"C:\Program Files (x86)\Inno Setup 6\ISCC.exe" "Jellyfin MPV Desktop.iss"
|
||||
xcopy /E /Y mpv32\mpv-1.dll dist\run\
|
||||
"C:\Program Files (x86)\Inno Setup 6\ISCC.exe" "Jellyfin MPV Shim.iss"
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
@ -1,13 +1,5 @@
|
||||
@echo off
|
||||
rd /s /q __pycache__ build
|
||||
rd /s /q dist\run-desktop
|
||||
rd /s /q dist\run
|
||||
set PATH=%PATH%;%CD%
|
||||
rem Edge-based build
|
||||
rem pyinstaller -c --add-binary "mpv-1.dll;." --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\webclient_view\webclient;jellyfin_mpv_shim\webclient_view\webclient" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --icon jellyfin.ico run-desktop-edge.py
|
||||
rem CEF-based build
|
||||
pyinstaller -c --add-binary "mpv-1.dll;." --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\webclient_view\webclient;jellyfin_mpv_shim\webclient_view\webclient" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --icon jellyfin.ico run-desktop.py
|
||||
xcopy /E /Y cef\cefpython3 dist\run-desktop\
|
||||
del dist\run-desktop\run-desktop.exe.manifest
|
||||
copy hidpi.manifest dist\run-desktop\run-desktop.exe.manifest
|
||||
rem rd /s /q __pycache__ build
|
||||
rem pyinstaller -cF --add-binary "mpv-1.dll;." --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --exclude-module cefpython3 --icon jellyfin.ico run.py
|
||||
pyinstaller -c --add-binary "mpv-1.dll;." --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --icon jellyfin.ico run.py
|
||||
|
@ -1,16 +1,10 @@
|
||||
@echo off
|
||||
rd /s /q __pycache__ dist build
|
||||
set PATH=%PATH%;%CD%
|
||||
rem Edge-based build
|
||||
rem pyinstaller -w --add-binary "mpv-1.dll;." --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --hidden-import pystray._win32 --add-data "jellyfin_mpv_shim\webclient_view\webclient;jellyfin_mpv_shim\webclient_view\webclient" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --icon jellyfin.ico run-desktop-edge.py
|
||||
rem CEF-based build
|
||||
pyinstaller -w --add-binary "mpv-1.dll;." --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --hidden-import pystray._win32 --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\webclient_view\webclient;jellyfin_mpv_shim\webclient_view\webclient" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --icon jellyfin.ico run-desktop.py
|
||||
pyinstaller -w --add-binary "mpv-1.dll;." --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --hidden-import pystray._win32 --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --icon jellyfin.ico run.py
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
xcopy /E /Y cef\cefpython3 dist\run-desktop\
|
||||
del dist\run-desktop\run-desktop.exe.manifest
|
||||
copy hidpi.manifest dist\run-desktop\run-desktop.exe.manifest
|
||||
rd /s /q __pycache__ build
|
||||
pyinstaller -wF --add-binary "mpv-1.dll;." --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --hidden-import pystray._win32 --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --exclude-module cefpython3 --icon jellyfin.ico run.py
|
||||
pyinstaller -wF --add-binary "mpv-1.dll;." --add-data "jellyfin_mpv_shim\systray.png;jellyfin_mpv_shim" --hidden-import pystray._win32 --add-data "jellyfin_mpv_shim\mouse.lua;jellyfin_mpv_shim" --add-data "jellyfin_mpv_shim\default_shader_pack;jellyfin_mpv_shim\default_shader_pack" --add-data "jellyfin_mpv_shim\messages;jellyfin_mpv_shim\messages" --add-data "jellyfin_mpv_shim\display_mirror\index.html;jellyfin_mpv_shim\display_mirror" --add-data "jellyfin_mpv_shim\display_mirror\jellyfin.css;jellyfin_mpv_shim\display_mirror" --add-binary "Microsoft.Toolkit.Forms.UI.Controls.WebView.dll;." --icon jellyfin.ico run.py
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
"C:\Program Files (x86)\Inno Setup 6\ISCC.exe" "Jellyfin MPV Desktop.iss"
|
||||
"C:\Program Files (x86)\Inno Setup 6\ISCC.exe" "Jellyfin MPV Shim.iss"
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
30
gen_pkg.sh
30
gen_pkg.sh
@ -59,18 +59,17 @@ elif [[ "$1" == "--gen-fingerprint" ]]
|
||||
then
|
||||
(
|
||||
get_resource_version pyinstaller/pyinstaller
|
||||
get_resource_version iwalton3/jellyfin-web
|
||||
get_resource_version iwalton3/default-shader-pack
|
||||
) | tee az-cache-fingerprint.list
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Verify versioning
|
||||
current_version=$(get_resource_version jellyfin/jellyfin-desktop)
|
||||
current_version=$(get_resource_version jellyfin/jellyfin-mpv-shim)
|
||||
current_version=${current_version:1}
|
||||
constants_version=$(cat jellyfin_mpv_shim/constants.py | grep '^CLIENT_VERSION' | cut -d '"' -f 2)
|
||||
setup_version=$(grep 'version=' setup.py | cut -d '"' -f 2)
|
||||
iss_version=$(grep '^#define MyAppVersion' "Jellyfin MPV Desktop.iss" | cut -d '"' -f 2)
|
||||
iss_version=$(grep '^#define MyAppVersion' "Jellyfin MPV Shim.iss" | cut -d '"' -f 2)
|
||||
appdata_version=$(grep 'release version="' jellyfin_mpv_shim/integration/com.github.iwalton3.jellyfin-mpv-shim.appdata.xml | \
|
||||
head -n 1 | cut -d '"' -f 2)
|
||||
|
||||
@ -93,31 +92,6 @@ do
|
||||
msgfmt "$file" -o "${file%.*}.mo"
|
||||
done
|
||||
|
||||
# Download web client
|
||||
update_web_client="no"
|
||||
if [[ ! -e "jellyfin_mpv_shim/webclient_view/webclient" ]]
|
||||
then
|
||||
update_web_client="yes"
|
||||
elif [[ -e ".last_wc_version" ]]
|
||||
then
|
||||
if [[ "$(get_resource_version iwalton3/jellyfin-web)" != "$(cat .last_wc_version)" ]]
|
||||
then
|
||||
update_web_client="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$update_web_client" == "yes" ]]
|
||||
then
|
||||
echo "Downloading web client..."
|
||||
wc_version=$(get_resource_version iwalton3/jellyfin-web)
|
||||
download_compat dist.zip "https://github.com/iwalton3/jellyfin-web/releases/download/$wc_version/dist.zip" "wc"
|
||||
rm -r jellyfin_mpv_shim/webclient_view/webclient 2> /dev/null
|
||||
rm -r dist 2> /dev/null
|
||||
unzip dist.zip > /dev/null && rm dist.zip
|
||||
mv dist jellyfin_mpv_shim/webclient_view/webclient
|
||||
echo "$wc_version" > .last_wc_version
|
||||
fi
|
||||
|
||||
# Download default-shader-pack
|
||||
update_shader_pack="no"
|
||||
if [[ ! -e "jellyfin_mpv_shim/default_shader_pack" ]]
|
||||
|
@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity language="*" name="Microsoft.Windows.Common-Controls" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" type="win32" version="6.0.0.0"/>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
@ -57,10 +57,6 @@ class Settings(BaseModel):
|
||||
display_mirroring: bool = False
|
||||
log_decisions: bool = False
|
||||
mpv_log_level: str = "info"
|
||||
enable_desktop: bool = False
|
||||
desktop_fullscreen: bool = False
|
||||
desktop_keep_pos: bool = False
|
||||
desktop_keep_size: bool = True
|
||||
idle_when_paused: bool = False
|
||||
stop_idle: bool = False
|
||||
transcode_to_h265: bool = False
|
||||
@ -108,7 +104,6 @@ class Settings(BaseModel):
|
||||
check_updates: bool = True
|
||||
notify_updates: bool = True
|
||||
lang: Optional[str] = None
|
||||
desktop_scale: float = 1.0
|
||||
discord_presence: bool = False
|
||||
ignore_ssl_cert: bool = False
|
||||
menu_mouse: bool = True
|
||||
|
@ -1,6 +1,6 @@
|
||||
APP_NAME = "jellyfin-mpv-shim"
|
||||
USER_APP_NAME = "Jellyfin MPV Shim"
|
||||
CLIENT_VERSION = "1.10.4"
|
||||
CLIENT_VERSION = "2.0.0"
|
||||
USER_AGENT = "Jellyfin-MPV-Shim/%s" % CLIENT_VERSION
|
||||
CAPABILITIES = {
|
||||
"PlayableMediaTypes": "Video",
|
||||
|
@ -37,38 +37,18 @@ def bind(event_name: str):
|
||||
class EventHandler(object):
|
||||
mirror = None
|
||||
|
||||
def __init__(self):
|
||||
self.it_on_event = None
|
||||
self.it_event_set = set()
|
||||
|
||||
def handle_event(
|
||||
self,
|
||||
client: "JellyfinClient_type",
|
||||
event_name: str,
|
||||
arguments: dict,
|
||||
from_web=False,
|
||||
):
|
||||
# Pass GeneralCommands to desktop client when no media
|
||||
# is playing and the event doesn't come from the web client.
|
||||
if (
|
||||
event_name == "GeneralCommand"
|
||||
and not playerManager.is_playing()
|
||||
and self.it_on_event
|
||||
and (not from_web or arguments.get("Name") != "DisplayContent")
|
||||
):
|
||||
timelineManager.delay_idle()
|
||||
self.it_on_event("GeneralCommand", arguments)
|
||||
return
|
||||
|
||||
if event_name in bindings:
|
||||
log.debug("Handled Event {0}: {1}".format(event_name, arguments))
|
||||
bindings[event_name](self, client, event_name, arguments)
|
||||
else:
|
||||
log.debug("Unhandled Event {0}: {1}".format(event_name, arguments))
|
||||
|
||||
if self.it_on_event and event_name in self.it_event_set:
|
||||
self.it_on_event(event_name, arguments)
|
||||
|
||||
@bind("Play")
|
||||
def play_media(self, client: "JellyfinClient_type", _event_name, arguments: dict):
|
||||
play_command = arguments.get("PlayCommand")
|
||||
|
@ -5,14 +5,13 @@
|
||||
<metadata_license>FSFAP</metadata_license>
|
||||
<project_license>GPL-3.0</project_license>
|
||||
<name>Jellyfin MPV Shim</name>
|
||||
<summary>Official Desktop Client for Jellyfin Media Server</summary>
|
||||
<summary>Cast-only client for Jellyfin Media Server</summary>
|
||||
<developer_name>Ian Walton</developer_name>
|
||||
|
||||
<description>
|
||||
<p>
|
||||
Jellyfin MPV Shim is a client for the Jellyfin media server which plays media in the
|
||||
MPV media player. There is a desktop client mode which displays the Jellyfin Web App,
|
||||
as well as a less resource-intensive background shim application which opens MPV only
|
||||
MPV media player. The application runs in the background and opens MPV only
|
||||
when media is cast to the player. The player supports most file formats, allowing you
|
||||
to prevent needless transcoding of your media files on the server. The player also has
|
||||
advanced features, such as bulk subtitle updates and launching commands on events.
|
||||
@ -30,13 +29,13 @@
|
||||
<category>Player</category>
|
||||
</categories>
|
||||
|
||||
<url type="homepage">https://github.com/jellyfin/jellyfin-desktop</url>
|
||||
<url type="help">https://github.com/jellyfin/jellyfin-desktop/blob/master/README.md</url>
|
||||
<url type="bugtracker">https://github.com/jellyfin/jellyfin-desktop/issues</url>
|
||||
<url type="homepage">https://github.com/jellyfin/jellyfin-mpv-shim</url>
|
||||
<url type="help">https://github.com/jellyfin/jellyfin-mpv-shim/blob/master/README.md</url>
|
||||
<url type="bugtracker">https://github.com/jellyfin/jellyfin-mpv-shim/issues</url>
|
||||
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<caption>The desktop client</caption>
|
||||
<caption>The web app casting to MPV Shim</caption>
|
||||
<image type="source" width="802" height="602">https://user-images.githubusercontent.com/8078788/78717835-392d2c00-78ef-11ea-9731-7fd4a1d8ebbe.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
@ -50,16 +49,21 @@
|
||||
</screenshots>
|
||||
|
||||
<launchable type="desktop-id">com.github.iwalton3.jellyfin-mpv-shim.desktop</launchable>
|
||||
<launchable type="desktop-id">com.github.iwalton3.jellyfin-mpv-shim.desktop-player.desktop</launchable>
|
||||
|
||||
<url type="homepage">https://github.com/jellyfin/jellyfin-desktop</url>
|
||||
<url type="homepage">https://github.com/jellyfin/jellyfin-mpv-shim</url>
|
||||
|
||||
<provides>
|
||||
<binary>jellyfin-mpv-desktop</binary>
|
||||
<binary>jellyfin-mpv-shim</binary>
|
||||
</provides>
|
||||
|
||||
<content_rating type="oars-1.1" />
|
||||
<releases>
|
||||
<release version="2.0.0" date="2021-04-19">
|
||||
<description>
|
||||
<p>This release drops the desktop webview mode.</p>
|
||||
<p>Please use Jellyfin Media Player instead or cast to the application. You can set MPV Shim as the default target in the web player as of 10.7.0.</p>
|
||||
</description>
|
||||
</release>
|
||||
<release version="1.10.4" date="2021-04-13">
|
||||
<description>
|
||||
<p>Changes:</p>
|
||||
|
@ -1,6 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Name=Jellyfin MPV Shim
|
||||
Exec=jellyfin-mpv-desktop --shim
|
||||
Exec=jellyfin-mpv-shim
|
||||
Type=Application
|
||||
Icon=com.github.iwalton3.jellyfin-mpv-shim
|
||||
Categories=Video;AudioVideo;TV;Player
|
||||
|
@ -1,6 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Jellyfin MPV Desktop
|
||||
Exec=jellyfin-mpv-desktop
|
||||
Type=Application
|
||||
Icon=com.github.iwalton3.jellyfin-mpv-shim
|
||||
Categories=Video;AudioVideo;TV;Player
|
@ -17,7 +17,7 @@ log = logging.getLogger("")
|
||||
logging.getLogger("requests").setLevel(logging.CRITICAL)
|
||||
|
||||
|
||||
def main(desktop: bool = False, cef: bool = False):
|
||||
def main():
|
||||
conf_file = conffile.get(APP_NAME, "conf.json")
|
||||
load_success = settings.load(conf_file)
|
||||
i18n.configure()
|
||||
@ -36,14 +36,8 @@ def main(desktop: bool = False, cef: bool = False):
|
||||
mirror = None
|
||||
use_gui = False
|
||||
gui_ready = None
|
||||
use_webview = desktop or settings.enable_desktop
|
||||
get_webview = lambda: None
|
||||
if use_webview:
|
||||
from .webclient_view import WebviewClient
|
||||
|
||||
user_interface = WebviewClient(cef=cef)
|
||||
get_webview = user_interface.get_webview
|
||||
elif settings.enable_gui:
|
||||
get_webview = None
|
||||
if settings.enable_gui:
|
||||
try:
|
||||
from .gui_mgr import user_interface
|
||||
|
||||
@ -56,7 +50,7 @@ def main(desktop: bool = False, cef: bool = False):
|
||||
exc_info=True,
|
||||
)
|
||||
|
||||
if settings.display_mirroring and not use_webview:
|
||||
if settings.display_mirroring:
|
||||
try:
|
||||
from .display_mirror import mirror
|
||||
|
||||
@ -89,9 +83,7 @@ def main(desktop: bool = False, cef: bool = False):
|
||||
log.info("Tip: Open the JSON file in VS Code to see what is wrong.")
|
||||
|
||||
try:
|
||||
if use_webview:
|
||||
user_interface.run()
|
||||
elif mirror:
|
||||
if mirror:
|
||||
user_interface.stop_callback = mirror.stop
|
||||
# If the webview runs before the systray icon, it fails.
|
||||
if use_gui:
|
||||
@ -113,10 +105,5 @@ def main(desktop: bool = False, cef: bool = False):
|
||||
user_interface.stop()
|
||||
|
||||
|
||||
def main_desktop(cef: bool = False):
|
||||
desktop = "--shim" not in sys.argv
|
||||
main(desktop, cef)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -152,7 +152,6 @@ class PlayerManager(object):
|
||||
self.warned_about_transcode = False
|
||||
self.fullscreen_disable = False
|
||||
self.update_check = UpdateChecker(self)
|
||||
self.on_playstate = None
|
||||
|
||||
if is_using_ext_mpv:
|
||||
mpv_options.update(
|
||||
@ -440,9 +439,7 @@ class PlayerManager(object):
|
||||
|
||||
if settings.log_decisions:
|
||||
log.debug("Playing: {0}".format(url))
|
||||
if self.get_webview() is not None and (
|
||||
settings.display_mirroring or settings.desktop_fullscreen
|
||||
):
|
||||
if self.get_webview() is not None and settings.display_mirroring:
|
||||
# noinspection PyUnresolvedReferences
|
||||
self.get_webview().hide()
|
||||
|
||||
@ -875,10 +872,7 @@ class PlayerManager(object):
|
||||
and self._video
|
||||
and not self._player.playback_abort
|
||||
):
|
||||
options = self.get_timeline_options()
|
||||
if self.on_playstate:
|
||||
self.on_playstate("initial", options, self._video.item)
|
||||
self._video.client.jellyfin.session_progress(options)
|
||||
self._video.client.jellyfin.session_progress(self.get_timeline_options())
|
||||
try:
|
||||
if self.syncplay.is_enabled():
|
||||
self.syncplay.sync_playback_time()
|
||||
@ -887,10 +881,7 @@ class PlayerManager(object):
|
||||
|
||||
@synchronous("_tl_lock")
|
||||
def send_timeline_initial(self):
|
||||
options = self.get_timeline_options()
|
||||
if self.on_playstate:
|
||||
self.on_playstate("initial", options, self._video.item)
|
||||
self._video.client.jellyfin.session_playing(options)
|
||||
self._video.client.jellyfin.session_playing(self.get_timeline_options())
|
||||
|
||||
@synchronous("_tl_lock")
|
||||
def send_timeline_stopped(self, finished=False, options=None, client=None):
|
||||
@ -902,13 +893,9 @@ class PlayerManager(object):
|
||||
if client is None:
|
||||
client = self._video.client
|
||||
|
||||
if self.on_playstate:
|
||||
self.on_playstate("stopped", options)
|
||||
client.jellyfin.session_stop(options)
|
||||
|
||||
if self.get_webview() is not None and (
|
||||
settings.display_mirroring or settings.desktop_fullscreen
|
||||
):
|
||||
if self.get_webview() is not None and settings.display_mirroring:
|
||||
self.get_webview().show()
|
||||
|
||||
if discord_presence:
|
||||
|
@ -14,7 +14,7 @@ if TYPE_CHECKING:
|
||||
|
||||
log = logging.getLogger("update_check")
|
||||
|
||||
release_url = "https://github.com/jellyfin/jellyfin-desktop/releases/"
|
||||
release_url = "https://github.com/jellyfin/jellyfin-mpv-shim/releases/"
|
||||
release_urls = [
|
||||
release_url,
|
||||
"https://github.com/jellyfin/jellyfin-mpv-shim/releases/",
|
||||
|
@ -1,436 +0,0 @@
|
||||
from queue import Empty, Queue
|
||||
import threading
|
||||
import time
|
||||
import urllib.request
|
||||
from werkzeug.serving import make_server
|
||||
from flask import Flask, request, jsonify
|
||||
from time import sleep
|
||||
import os.path
|
||||
import json
|
||||
import base64
|
||||
|
||||
# So, most of my use of the webview library is ugly but there's a reason for this!
|
||||
# Debian's python3-webview package is super old (2.3), pip3's pywebview package is much newer (3.2).
|
||||
# I would just say "fuck it, install from testing/backports/unstable" except that's not any newer either.
|
||||
# So instead I'm going to try supporting *both* here, which gets rather ugly because they made very significant changes.
|
||||
#
|
||||
# The key differences seem to be:
|
||||
# 3.2's create_window() returns a Window object immediately, then you need to call start()
|
||||
# 2.3's create_window() blocks forever effectivelly calling start() itself
|
||||
#
|
||||
# 3.2's Window has a .loaded Event that you need to subscribe to notice when the window is ready for input
|
||||
# 2.3 has a webview_ready() function that blocks until webview is ready (or timeout is passed)
|
||||
import webview # Python3-webview in Debian, pywebview in pypi
|
||||
import sys
|
||||
from threading import Event
|
||||
import datetime
|
||||
|
||||
from ..clients import clientManager
|
||||
from ..player import playerManager
|
||||
from ..conf import settings
|
||||
from ..event_handler import eventHandler
|
||||
from ..constants import CAPABILITIES, CLIENT_VERSION, USER_APP_NAME, APP_NAME
|
||||
from ..utils import get_resource
|
||||
from .. import conffile
|
||||
import logging
|
||||
|
||||
log = logging.getLogger("webclient")
|
||||
|
||||
remember_layout = conffile.get(APP_NAME, "layout.json")
|
||||
|
||||
|
||||
def do_not_cache(response):
|
||||
response.cache_control.no_store = True
|
||||
if response.cache_control.max_age:
|
||||
response.cache_control.max_age = None
|
||||
if response.cache_control.public:
|
||||
response.cache_control.public = False
|
||||
|
||||
|
||||
# Based on https://stackoverflow.com/questions/15562446/
|
||||
class Server(threading.Thread):
|
||||
def __init__(self):
|
||||
self.srv = None
|
||||
self.ctx = None
|
||||
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
def stop(self):
|
||||
if self.srv is not None:
|
||||
self.srv.shutdown()
|
||||
self.join()
|
||||
|
||||
def run(self):
|
||||
app = Flask(
|
||||
__name__,
|
||||
static_url_path="",
|
||||
static_folder=get_resource("webclient_view", "webclient"),
|
||||
)
|
||||
|
||||
pl_event_queue = Queue()
|
||||
last_server_id = ""
|
||||
last_user_id = ""
|
||||
last_user_name = ""
|
||||
|
||||
def wrap_playstate(active, playstate=None, item=None):
|
||||
if playstate is None:
|
||||
playstate = {
|
||||
"CanSeek": False,
|
||||
"IsPaused": False,
|
||||
"IsMuted": False,
|
||||
"RepeatMode": "RepeatNone",
|
||||
}
|
||||
res = {
|
||||
"PlayState": playstate,
|
||||
"AdditionalUsers": [],
|
||||
"Capabilities": {
|
||||
"PlayableMediaTypes": CAPABILITIES["PlayableMediaTypes"].split(","),
|
||||
"SupportedCommands": CAPABILITIES["SupportedCommands"].split(","),
|
||||
"SupportsMediaControl": True,
|
||||
"SupportsContentUploading": False,
|
||||
"SupportsPersistentIdentifier": False,
|
||||
"SupportsSync": False,
|
||||
},
|
||||
"RemoteEndPoint": "0.0.0.0",
|
||||
"PlayableMediaTypes": CAPABILITIES["PlayableMediaTypes"].split(","),
|
||||
"Id": settings.client_uuid,
|
||||
"UserId": last_user_id,
|
||||
"UserName": last_user_name,
|
||||
"Client": USER_APP_NAME,
|
||||
"LastActivityDate": datetime.datetime.utcnow().isoformat(),
|
||||
"LastPlaybackCheckIn": "0001-01-01T00:00:00.0000000Z",
|
||||
"DeviceName": settings.player_name,
|
||||
"DeviceId": settings.client_uuid,
|
||||
"ApplicationVersion": CLIENT_VERSION,
|
||||
"IsActive": active,
|
||||
"SupportsMediaControl": True,
|
||||
"SupportsRemoteControl": True,
|
||||
"HasCustomDeviceName": False,
|
||||
"ServerId": last_server_id,
|
||||
"SupportedCommands": CAPABILITIES["SupportedCommands"].split(","),
|
||||
"dest": "player",
|
||||
}
|
||||
if "NowPlayingQueue" in playstate:
|
||||
res["NowPlayingQueue"] = playstate["NowPlayingQueue"]
|
||||
if "PlaylistItemId" in playstate:
|
||||
res["PlaylistItemId"] = playstate["PlaylistItemId"]
|
||||
if item:
|
||||
res["NowPlayingItem"] = item
|
||||
return res
|
||||
|
||||
def on_playstate(state, payload=None, item=None):
|
||||
pl_event_queue.put(wrap_playstate(True, payload, item))
|
||||
if state == "stopped":
|
||||
pl_event_queue.put(wrap_playstate(False))
|
||||
|
||||
def it_on_event(name, event):
|
||||
server_id = event["ServerId"]
|
||||
if type(event) is dict and "value" in event and len(event) == 2:
|
||||
event = event["value"]
|
||||
pl_event_queue.put(
|
||||
{
|
||||
"dest": "ws",
|
||||
"MessageType": name,
|
||||
"Data": event,
|
||||
"ServerId": server_id,
|
||||
}
|
||||
)
|
||||
|
||||
playerManager.on_playstate = on_playstate
|
||||
eventHandler.it_on_event = it_on_event
|
||||
eventHandler.it_event_set = {
|
||||
"ActivityLogEntry",
|
||||
"LibraryChanged",
|
||||
"PackageInstallationCancelled",
|
||||
"PackageInstallationCompleted",
|
||||
"PackageInstallationFailed",
|
||||
"PackageInstalling",
|
||||
"RefreshProgress",
|
||||
"RestartRequired",
|
||||
"ScheduledTasksInfo",
|
||||
"SeriesTimerCancelled",
|
||||
"SeriesTimerCancelled",
|
||||
"SeriesTimerCreated",
|
||||
"SeriesTimerCreated",
|
||||
"ServerRestarting",
|
||||
"ServerShuttingDown",
|
||||
"Sessions",
|
||||
"TimerCancelled",
|
||||
"TimerCreated",
|
||||
"UserDataChanged",
|
||||
}
|
||||
|
||||
@app.after_request
|
||||
def add_header(response):
|
||||
if request.path == "/index.html":
|
||||
do_not_cache(response)
|
||||
client_data = base64.b64encode(
|
||||
json.dumps(
|
||||
{
|
||||
"appName": USER_APP_NAME,
|
||||
"appVersion": CLIENT_VERSION,
|
||||
"deviceName": settings.player_name,
|
||||
"deviceId": settings.client_uuid,
|
||||
}
|
||||
).encode("ascii")
|
||||
)
|
||||
# We need access to this data before we can make an async web call.
|
||||
replacement = (
|
||||
b"""<body><script type="application/json" id="clientData">%s</script>"""
|
||||
% client_data
|
||||
)
|
||||
if settings.desktop_scale != 1.0:
|
||||
f_scale = float(settings.desktop_scale)
|
||||
replacement = replacement + (
|
||||
b"""<style>body { zoom: %.2f; }</style>""" % f_scale
|
||||
)
|
||||
response.make_sequence()
|
||||
response.set_data(response.get_data().replace(b"<body>", replacement,))
|
||||
|
||||
return response
|
||||
if not response.cache_control.no_store:
|
||||
response.cache_control.max_age = 2592000
|
||||
return response
|
||||
|
||||
@app.route("/mpv_shim_session", methods=["POST"])
|
||||
def mpv_shim_session():
|
||||
nonlocal last_server_id, last_user_id, last_user_name
|
||||
if request.headers["Content-Type"] != "application/json; charset=UTF-8":
|
||||
return "Go Away"
|
||||
req = request.json
|
||||
log.info(
|
||||
"Recieved session for server: {0}, user: {1}".format(
|
||||
req["Name"], req["username"]
|
||||
)
|
||||
)
|
||||
if req["Id"] not in clientManager.clients:
|
||||
is_logged_in = clientManager.connect_client(req)
|
||||
log.info("Connection was successful.")
|
||||
else:
|
||||
is_logged_in = True
|
||||
log.info("Ignoring as client already exists.")
|
||||
last_server_id = req["Id"]
|
||||
last_user_id = req["UserId"]
|
||||
last_user_name = req["username"]
|
||||
resp = jsonify({"success": is_logged_in})
|
||||
resp.status_code = 200 if is_logged_in else 500
|
||||
do_not_cache(resp)
|
||||
return resp
|
||||
|
||||
@app.route("/mpv_shim_event", methods=["POST"])
|
||||
def mpv_shim_event():
|
||||
if request.headers["Content-Type"] != "application/json; charset=UTF-8":
|
||||
return "Go Away"
|
||||
try:
|
||||
queue_item = pl_event_queue.get(timeout=5)
|
||||
except Empty:
|
||||
queue_item = {}
|
||||
resp = jsonify(queue_item)
|
||||
resp.status_code = 200
|
||||
do_not_cache(resp)
|
||||
return resp
|
||||
|
||||
@app.route("/mpv_shim_message", methods=["POST"])
|
||||
def mpv_shim_message():
|
||||
if request.headers["Content-Type"] != "application/json; charset=UTF-8":
|
||||
return "Go Away"
|
||||
req = request.json
|
||||
client = clientManager.clients.get(req["payload"]["ServerId"])
|
||||
resp = jsonify({})
|
||||
resp.status_code = 200
|
||||
do_not_cache(resp)
|
||||
if client is None:
|
||||
log.warning("Message recieved but no client available. Ignoring.")
|
||||
return resp
|
||||
eventHandler.handle_event(
|
||||
client, req["name"], req["payload"], from_web=True
|
||||
)
|
||||
return resp
|
||||
|
||||
@app.route("/mpv_shim_wsmessage", methods=["POST"])
|
||||
def mpv_shim_wsmessage():
|
||||
if request.headers["Content-Type"] != "application/json; charset=UTF-8":
|
||||
return "Go Away"
|
||||
req = request.json
|
||||
client = clientManager.clients.get(req["ServerId"])
|
||||
resp = jsonify({})
|
||||
resp.status_code = 200
|
||||
do_not_cache(resp)
|
||||
if client is None:
|
||||
log.warning("Message recieved but no client available. Ignoring.")
|
||||
return resp
|
||||
client.wsc.send(req["name"], req.get("payload", ""))
|
||||
return resp
|
||||
|
||||
@app.route("/mpv_shim_teardown", methods=["POST"])
|
||||
def mpv_shim_teardown():
|
||||
if request.headers["Content-Type"] != "application/json; charset=UTF-8":
|
||||
return "Go Away"
|
||||
log.info("Client teardown requested.")
|
||||
clientManager.stop_all_clients()
|
||||
resp = jsonify({})
|
||||
resp.status_code = 200
|
||||
do_not_cache(resp)
|
||||
return resp
|
||||
|
||||
@app.route("/mpv_shim_syncplay_join", methods=["POST"])
|
||||
def mpv_shim_join():
|
||||
if request.headers["Content-Type"] != "application/json; charset=UTF-8":
|
||||
return "Go Away"
|
||||
req = request.json
|
||||
client = list(clientManager.clients.values())[0]
|
||||
playerManager.syncplay.client = client
|
||||
playerManager.syncplay.join_group(req["GroupId"])
|
||||
resp = jsonify({})
|
||||
resp.status_code = 200
|
||||
do_not_cache(resp)
|
||||
return resp
|
||||
|
||||
self.srv = make_server("127.0.0.1", 18096, app, threaded=True)
|
||||
self.ctx = app.app_context()
|
||||
self.ctx.push()
|
||||
self.srv.serve_forever()
|
||||
|
||||
|
||||
# This makes me rather uncomfortable, but there's no easy way around this other than
|
||||
# importing display_mirror in helpers. Lambda needed because the 2.3 version of the JS
|
||||
# api adds an argument even when not used.
|
||||
class WebviewClient(object):
|
||||
def __init__(self, cef=False):
|
||||
self.open_player_menu = lambda: None
|
||||
self.server = Server()
|
||||
self.cef = cef
|
||||
self.webview = None
|
||||
|
||||
def start(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def login_servers():
|
||||
pass
|
||||
|
||||
def get_webview(self):
|
||||
return self.webview
|
||||
|
||||
def run(self):
|
||||
self.server.start()
|
||||
|
||||
extra_options = {}
|
||||
if os.path.exists(remember_layout):
|
||||
with open(remember_layout) as fh:
|
||||
layout_options = json.load(fh)
|
||||
if (
|
||||
settings.desktop_keep_pos
|
||||
and layout_options.get("x")
|
||||
and layout_options.get("y")
|
||||
):
|
||||
extra_options["x"] = layout_options["x"]
|
||||
extra_options["y"] = layout_options["y"]
|
||||
if (
|
||||
settings.desktop_keep_size
|
||||
and layout_options.get("width")
|
||||
and layout_options.get("height")
|
||||
):
|
||||
extra_options["width"] = layout_options["width"]
|
||||
extra_options["height"] = layout_options["height"]
|
||||
else:
|
||||
# Set a reasonable window size
|
||||
extra_options.update({"width": 1280, "height": 720})
|
||||
if (
|
||||
not self.cef
|
||||
and sys.platform.startswith("win32")
|
||||
or sys.platform.startswith("cygwin")
|
||||
):
|
||||
# I wasted half a day here. Turns out that pywebview does something that
|
||||
# breaks Jellyfin on Windows in both EdgeHTML and CEF. This kills that.
|
||||
try:
|
||||
from webview.platforms import winforms
|
||||
|
||||
winforms.BrowserView.EdgeHTML.on_navigation_completed = lambda: None
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Apparently pywebview3 breaks everywhere, not just on Windows.
|
||||
if self.cef:
|
||||
try:
|
||||
from webview.platforms import cef
|
||||
|
||||
cef.settings.update({"cache_path": conffile.get(APP_NAME, "cache")})
|
||||
cef.Browser.initialize = lambda self: None
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
from webview.platforms import cocoa
|
||||
|
||||
def override_cocoa(_self, webview, _nav):
|
||||
# Add the webview to the window if it's not yet the contentView
|
||||
i = cocoa.BrowserView.get_instance("webkit", webview)
|
||||
|
||||
if i:
|
||||
if not webview.window():
|
||||
i.window.setContentView_(webview)
|
||||
i.window.makeFirstResponder_(webview)
|
||||
|
||||
cocoa.BrowserView.BrowserDelegate.webView_didFinishNavigation_ = (
|
||||
override_cocoa
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
from webview.platforms import gtk
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
def override_gtk(_self, webview, _status):
|
||||
if not webview.props.opacity:
|
||||
gtk.glib.idle_add(webview.set_opacity, 1.0)
|
||||
|
||||
gtk.BrowserView.on_load_finish = override_gtk
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
from webview.platforms import qt
|
||||
|
||||
qt.BrowserView.on_load_finished = lambda self: None
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
url = "http://127.0.0.1:18096/index.html"
|
||||
# Wait until the server is ready.
|
||||
while True:
|
||||
try:
|
||||
urllib.request.urlopen(url)
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
sleep(0.1)
|
||||
|
||||
# Webview needs to be run in the MainThread.
|
||||
window = webview.create_window(
|
||||
url=url,
|
||||
title="Jellyfin MPV Desktop",
|
||||
fullscreen=settings.desktop_fullscreen,
|
||||
**extra_options
|
||||
)
|
||||
if window is not None:
|
||||
self.webview = window
|
||||
|
||||
def handle_close():
|
||||
x, y = window.x, window.y
|
||||
extra_options = {
|
||||
"x": x,
|
||||
"y": y,
|
||||
"width": window.width,
|
||||
"height": window.height,
|
||||
}
|
||||
with open(remember_layout, "w") as fh:
|
||||
json.dump(extra_options, fh)
|
||||
|
||||
window.closing += handle_close
|
||||
if self.cef:
|
||||
webview.start(gui="cef")
|
||||
else:
|
||||
webview.start()
|
||||
self.server.stop()
|
||||
|
||||
def stop(self):
|
||||
self.server.stop()
|
@ -1,23 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Newer revisions of python-mpv require mpv-1.dll in the PATH.
|
||||
import os
|
||||
import sys
|
||||
import multiprocessing
|
||||
|
||||
if sys.platform.startswith("win32") or sys.platform.startswith("cygwin"):
|
||||
# Detect if bundled via pyinstaller.
|
||||
# From: https://stackoverflow.com/questions/404744/
|
||||
if getattr(sys, "frozen", False):
|
||||
application_path = getattr(sys, "_MEIPASS")
|
||||
else:
|
||||
application_path = os.path.dirname(os.path.abspath(__file__))
|
||||
os.environ["PATH"] = application_path + os.pathsep + os.environ["PATH"]
|
||||
|
||||
from jellyfin_mpv_shim.mpv_shim import main_desktop
|
||||
|
||||
if __name__ == "__main__":
|
||||
# https://stackoverflow.com/questions/24944558/pyinstaller-built-windows-exe-fails-with-multiprocessing
|
||||
multiprocessing.freeze_support()
|
||||
|
||||
main_desktop()
|
@ -1,23 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Newer revisions of python-mpv require mpv-1.dll in the PATH.
|
||||
import os
|
||||
import sys
|
||||
import multiprocessing
|
||||
|
||||
if sys.platform.startswith("win32") or sys.platform.startswith("cygwin"):
|
||||
# Detect if bundled via pyinstaller.
|
||||
# From: https://stackoverflow.com/questions/404744/
|
||||
if getattr(sys, "frozen", False):
|
||||
application_path = getattr(sys, "_MEIPASS")
|
||||
else:
|
||||
application_path = os.path.dirname(os.path.abspath(__file__))
|
||||
os.environ["PATH"] = application_path + os.pathsep + os.environ["PATH"]
|
||||
|
||||
from jellyfin_mpv_shim.mpv_shim import main_desktop
|
||||
|
||||
if __name__ == "__main__":
|
||||
# https://stackoverflow.com/questions/24944558/pyinstaller-built-windows-exe-fails-with-multiprocessing
|
||||
multiprocessing.freeze_support()
|
||||
|
||||
main_desktop(cef=True)
|
@ -1,20 +1,19 @@
|
||||
from setuptools import setup
|
||||
|
||||
APP = ["/usr/local/bin/jellyfin-mpv-desktop"]
|
||||
APP = ["/usr/local/bin/jellyfin-mpv-shim"]
|
||||
OPTIONS = {
|
||||
"argv_emulation": True,
|
||||
"iconfile": "jellyfin.icns",
|
||||
"resources": [
|
||||
"/usr/local/bin/mpv",
|
||||
"/usr/local/bin/jellyfin-mpv-shim",
|
||||
"/usr/local/lib/python3.9/site-packages/jellyfin_mpv_shim/webclient_view",
|
||||
"/usr/local/bin/jellyfin-mpv-shim"
|
||||
],
|
||||
"packages": ["pkg_resources"],
|
||||
}
|
||||
|
||||
setup(
|
||||
app=APP,
|
||||
name="Jellyfin MPV Desktop",
|
||||
name="Jellyfin MPV Shim",
|
||||
options={"py2app": OPTIONS},
|
||||
setup_requires=["py2app"],
|
||||
)
|
||||
|
14
setup.py
14
setup.py
@ -5,18 +5,17 @@ with open("README.md", "r") as fh:
|
||||
|
||||
setup(
|
||||
name="jellyfin-mpv-shim",
|
||||
version="1.10.4",
|
||||
version="2.0.0",
|
||||
author="Ian Walton",
|
||||
author_email="iwalton3@gmail.com",
|
||||
description="Cast media from Jellyfin Mobile and Web apps to MPV.",
|
||||
license="GPLv3",
|
||||
long_description=open("README.md").read(),
|
||||
long_description_content_type="text/markdown",
|
||||
url="https://github.com/jellyfin/jellyfin-desktop",
|
||||
url="https://github.com/jellyfin/jellyfin-mpv-shim",
|
||||
packages=[
|
||||
"jellyfin_mpv_shim",
|
||||
"jellyfin_mpv_shim.display_mirror",
|
||||
"jellyfin_mpv_shim.webclient_view",
|
||||
"jellyfin_mpv_shim.display_mirror"
|
||||
],
|
||||
package_data={
|
||||
"jellyfin_mpv_shim.display_mirror": ["*.css", "*.html"],
|
||||
@ -24,9 +23,7 @@ setup(
|
||||
},
|
||||
entry_points={
|
||||
"console_scripts": [
|
||||
"jellyfin-mpv-shim=jellyfin_mpv_shim.mpv_shim:main",
|
||||
"jellyfin-mpv-desktop=jellyfin_mpv_shim.mpv_shim:main_desktop",
|
||||
"jellyfin-desktop=jellyfin_mpv_shim.mpv_shim:main_desktop",
|
||||
"jellyfin-mpv-shim=jellyfin_mpv_shim.mpv_shim:main"
|
||||
]
|
||||
},
|
||||
classifiers=[
|
||||
@ -37,14 +34,11 @@ setup(
|
||||
extras_require={
|
||||
"gui": ["pystray", "PIL"],
|
||||
"mirror": ["Jinja2", "pywebview>=3.3.1"],
|
||||
"desktop": ["Flask", "pywebview>=3.3.1", "Werkzeug"],
|
||||
"discord": ["pypresence"],
|
||||
"all": [
|
||||
"Jinja2",
|
||||
"pywebview>=3.3.1",
|
||||
"pystray",
|
||||
"Flask",
|
||||
"Werkzeug",
|
||||
"pypresence",
|
||||
],
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user