jellyfin / jellyfin-mpv-shim

MPV Cast Client for Jellyfin
Other
1.59k stars 93 forks source link

publish jellyfin-mpv-desktop compiled for mac (as an app / dmg ?) #60

Open krodelabestiole opened 4 years ago

krodelabestiole commented 4 years ago

thanks again for the flatpak ! https://github.com/iwalton3/jellyfin-mpv-shim/issues/47

following the same idea I think a compiled version for Mac OS would be awesome.

I've tried to create an .app file using py2app on my girlfriend's Mac Book and it compiled successfully : setup.py file containing :

"""
This is a setup.py script generated by py2applet

Usage:
    python setup.py py2app
"""

from setuptools import setup

APP = ['jellyfin-mpv-desktop']
DATA_FILES = ['jellyfin-mpv-shim']
OPTIONS = {
    'iconfile':'jellyfin.icns'
}

setup(
    app=APP,
    name='Jellyfin MPV Desktop',
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)

jellyfin.icns.zip then : python3 setup.py py2app No error so far...

but I have an error running the app :

Traceback (most recent call last):
  File "/Applications/jellyfin-mpv-desktop.app/Contents/Resources/__boot__.py", line 101, in <module>
    _run()
  File "/Applications/jellyfin-mpv-desktop.app/Contents/Resources/__boot__.py", line 84, in _run
    exec(compile(source, path, "exec"), globals(), globals())
  File "/Applications/jellyfin-mpv-desktop.app/Contents/Resources/jellyfin-mpv-desktop", line 5, in <module>
    from setuptools import setup
  File "setuptools/__init__.pyc", line 14, in <module>
  File "setuptools/extern/__init__.pyc", line 54, in load_module
ImportError: The 'six' package is required; normally this is bundled with this package so if you get this warning, consult the packager of your distribution.
2020-04-24 22:53:23.874 jellyfin-mpv-desktop[724:15238] jellyfin-mpv-desktop Error

Any idea on this ?

iwalton3 commented 4 years ago

It looks like the six library dependency isn’t getting bundled. Maybe try adding the required packages to the py2app setup script?

krodelabestiole commented 4 years ago

I just wonder how... I'm not skilled at all with Python... https://py2app.readthedocs.io/en/latest/

krodelabestiole commented 4 years ago

I just built it with python3 setup.py py2app --packages six and the error changed... I'm back working on it...

krodelabestiole commented 4 years ago

I imported six, pkg_resources and setuptools with :

from setuptools import setup

APP = ['jellyfin-mpv-desktop']
DATA_FILES = ['jellyfin-mpv-shim']
OPTIONS = {
    'iconfile':'jellyfin.icns',
    'packages':'six,pkg_resources,setuptools'
}

setup(
    app=APP,
    name='Jellyfin MPV Desktop',
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)

But now I run into a new error that looks trickier :

from distutils.command.install import INSTALL_SCHEMES, SCHEME_KEYS
  File "distutils/command/install.pyc", line 18, in <module>
ImportError: cannot import name 'USER_BASE' from 'site' (dist/Jellyfin MPV Desktop.app/Contents/Resources/site.pyc)
iwalton3 commented 4 years ago

Try adding 'includes': ['python-mpv', 'jellyfin-apiclient-python>=1.4.0', 'python-mpv-jsonipc>=1.1.9', 'Jinja2', 'pywebview', 'pystray', 'Flask', 'Werkzeug'] to OPTIONS. Remove the existing 'packages':'six,pkg_resources,setuptools' line.

It is worth noting however that if this packaging tool is anything like PyInstaller, you'll need to bundle natives and possibly make changes to the code for it to work.

krodelabestiole commented 4 years ago

argh I did plenty of mistakes previously and my jellyfin-mpv-desktop file py2app was trying to work on was not even the original one. using the good one it doesn't seem to be necessary to manually include any dependency, I'm so ashamed... still the error message I have now is that MPV doesn't seem to be included (I tried both with the manual includes and without) :

/Applications/Jellyfin\ MPV\ Desktop.app/Contents/MacOS/Jellyfin\ MPV\ Desktop
2020-04-25 04:54:01,731 [    INFO] conf: Loaded settings from json: /Users/kro/Library/Application Support/jellyfin-mpv-shim/conf.json
2020-04-25 04:54:01,887 [    INFO] player: Using external mpv playback backend.
2020-04-25 04:54:01,888 [   DEBUG] mpv-jsonipc: Staring MPV from mpv.
2020-04-25 04:54:01,888 [   DEBUG] mpv-jsonipc: Using IPC socket /tmp/mpv141201916862262 for MPV.
Traceback (most recent call last):
  File "/Applications/Jellyfin MPV Desktop.app/Contents/Resources/__boot__.py", line 101, in <module>
    _run()
  File "/Applications/Jellyfin MPV Desktop.app/Contents/Resources/__boot__.py", line 84, in _run
    exec(compile(source, path, "exec"), globals(), globals())
  File "/Applications/Jellyfin MPV Desktop.app/Contents/Resources/jellyfin-mpv-desktop", line 8, in <module>
    sys.exit(main_desktop())
  File "jellyfin_mpv_shim/mpv_shim.pyc", line 96, in main_desktop
  File "jellyfin_mpv_shim/mpv_shim.pyc", line 54, in main
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 668, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 638, in _load_backward_compatible
  File "jellyfin_mpv_shim/player.pyc", line 551, in <module>
  File "jellyfin_mpv_shim/player.pyc", line 103, in __init__
  File "python_mpv_jsonipc.pyc", line 385, in __init__
  File "python_mpv_jsonipc.pyc", line 197, in __init__
  File "subprocess.pyc", line 800, in __init__
  File "subprocess.pyc", line 1551, in _execute_child
FileNotFoundError: [Errno 2] No such file or directory: 'mpv': 'mpv'
2020-04-25 04:54:01.968 Jellyfin MPV Desktop[1120:52912] Jellyfin MPV Desktop Error

afterward I've added mpv like so with no success :

from setuptools import setup

APP = ['jellyfin-mpv-desktop']
DATA_FILES = ['jellyfin-mpv-shim','mpv']
OPTIONS = {
    'iconfile':'jellyfin.icns',
    'includes': ['python-mpv',
                 'jellyfin-apiclient-python>=1.4.0',
                 'python-mpv-jsonipc>=1.1.9',
                 'Jinja2',
                 'pywebview',
                 'pystray',
                 'Flask',
                 'Werkzeug'
                 ]
}

setup(
    app=APP,
    name='Jellyfin MPV Desktop',
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)
iwalton3 commented 4 years ago

Unfortunately I can't really help at this point.

krodelabestiole commented 4 years ago

ok, I think I'm close to something working with this setup.py :

from setuptools import setup

APP = ['jellyfin-mpv-desktop']
OPTIONS = {
    'argv_emulation' : True,
    'iconfile' : 'jellyfin.icns',
    'extra_scripts' : ['mpv']
}

setup(
    app=APP,
    name='Jellyfin MPV Desktop',
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)

Unfortunately I run into something that looks like a bug when running py2app including mpv :

Traceback (most recent call last):
File "setup.py", line 33, in <module>
setup_requires=['py2app'],
File "/usr/local/lib/python3.7/site-packages/setuptools/init.py", line 144, in setup
return distutils.core.setup(**attrs)
File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/distutils/core.py", line 148, in setup
dist.run_commands()
File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/distutils/dist.py", line 966, in run_commands
self.run_command(cmd)
File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/distutils/dist.py", line 985, in run_command
cmd_obj.run()
File "/usr/local/lib/python3.7/site-packages/py2app/build_app.py", line 907, in run
self._run()
File "/usr/local/lib/python3.7/site-packages/py2app/build_app.py", line 1125, in _run
self.run_normal()
File "/usr/local/lib/python3.7/site-packages/py2app/build_app.py", line 1218, in run_normal
mf = self.get_modulefinder()
File "/usr/local/lib/python3.7/site-packages/py2app/build_app.py", line 1067, in get_modulefinder
debug=debug,
File "/usr/local/lib/python3.7/site-packages/modulegraph/find_modules.py", line 321, in find_modules
find_needed_modules(mf, scripts, includes, packages)
File "/usr/local/lib/python3.7/site-packages/modulegraph/find_modules.py", line 226, in find_needed_modules
mf.run_script(path)
File "/usr/local/lib/python3.7/site-packages/modulegraph/modulegraph.py", line 1085, in run_script
contents = fp.read() + "\n"
File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/codecs.py", line 322, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xcf in position 0: invalid continuation byte
iwalton3 commented 4 years ago

Maybe try using resources? It looks like extra_scripts it tries to parse the files as text for some reason.

krodelabestiole commented 4 years ago

I tried with extra_script because it copies mpv at the same level a the main executable (and because of the not for code ! mention in the doc). no error with resources though. I tried to manually symlink or even copy mpv right next to it in the .app tree. JMD still can't fin mpv, I guess it should call it with ./mpvinstead of mpv to find it.

I guess the only way would be to add the mpv directory to PATH or something... With a script that would launch just before JMD... Maybe create a handler file that would do this before lauching the JMD app... I don't know much neither with mac OS nor with Python though...

iwalton3 commented 4 years ago

You could override what MPV executable is loaded here: https://github.com/iwalton3/jellyfin-mpv-shim/blob/master/jellyfin_mpv_shim/player.py#L97

Or tell users to configure the MPV location manually in the config file. (But this is less ideal.)

krodelabestiole commented 4 years ago

Thanks !

I changed this line with : "mpv_location": "../Resources/mpv", And now I don't have any error message. It is still not working though. Werkzeug returns an infinity of 404 :

/Applications/Jellyfin\ MPV\ Desktop.app/Contents/MacOS/Jellyfin\ MPV\ Desktop
2020-04-25 22:07:07,861 [    INFO] player: Using external mpv playback backend.
2020-04-25 22:07:07,863 [   DEBUG] mpv-jsonipc: Staring MPV from ../Resources/mpv.
2020-04-25 22:07:07,863 [   DEBUG] mpv-jsonipc: Using IPC socket /tmp/mpv229874874938631 for MPV.
2020-04-25 22:07:08,172 [   DEBUG] mpv-jsonipc: Found MPV socket.
2020-04-25 22:07:08,383 [    INFO] werkzeug: 127.0.0.1 - - [25/Apr/2020 22:07:08] "GET /index.html HTTP/1.1" 404 -
2020-04-25 22:07:08,507 [    INFO] werkzeug: 127.0.0.1 - - [25/Apr/2020 22:07:08] "GET /index.html HTTP/1.1" 404 -
2020-04-25 22:07:08,652 [    INFO] werkzeug: 127.0.0.1 - - [25/Apr/2020 22:07:08] "GET /index.html HTTP/1.1" 404 -
...
iwalton3 commented 4 years ago

Make sure the web client is downloaded and included. See: https://github.com/iwalton3/jellyfin-mpv-shim/blob/master/README.md#local-dev-installation

krodelabestiole commented 4 years ago

for a summary, here is what my setup.py looks like :

from setuptools import setup

APP = ['/usr/local/bin/jellyfin-mpv-desktop']
OPTIONS = {
    'argv_emulation' : True,
    'iconfile' : 'jellyfin.icns',
    'resources' : [
        '/usr/local/bin/mpv',
        '/usr/local/bin/jellyfin-mpv-shim',
        '/usr/local/lib/python3.7/site-packages/jellyfin_mpv_shim/webclient_view'
    ],
    'packages': [
        'pkg_resources'
    ]
}

setup(
    app=APP,
    name='Jellyfin MPV Desktop',
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)

which gives a Jellyfin MPV Desktop.app directory where :

Still 404s. I tried to add a symlink from MacOS/webclient_view to ../Resources/webclient_view. No success. I don't have any error message, and I don't get how / when this web client is called... What would be its path relative to Jellyfin MPV Desktop executable ?

iwalton3 commented 4 years ago

The location of the web client is specified here: https://github.com/iwalton3/jellyfin-mpv-shim/blob/master/jellyfin_mpv_shim/webclient_view/__init__.py#L55

Normally that resolves to jellyfin_mpv_shim/webclient_view/webclient/, which is the folder containing index.html.

krodelabestiole commented 4 years ago

the only way I found to make it work was to use an absolute path (from the root of the hard drive), which doesn't make it very portable : static_folder="/Applications/Jellyfin MPV Desktop.app/Contents/Resources/webclient_view/webclient") I couldn't find any working relative path :/ (I also have to add the pkg_resources package)

then I can launch the app (when it's in the /Applications directory) and connect to a server but there is no option for local broadcasting on MPV...

I will probably quit for now.

brukberhane commented 3 years ago

@krodelabestiole could you send me whatever code you've worked on up until now? I wanted to take a look at your work and see if I can change anything up. I'm still not sure where to even specify the absolute path for the webview so looking at your work could help me out.

krodelabestiole commented 3 years ago

@brukberhane sorry i used to work on a virtual machine and i changed my workstation since then. i will have a look if i can i find anything in a few days, i m not home at the moment.

HavermansStef commented 3 years ago

I've also had problems with installation on Mac before. Publishing as a DMG package seems like a nice addition to get more people without a Python background started.

brukberhane commented 3 years ago

I've been trying @krodelabestiole's methods to build it with py2app but I've ran into a problem with pydantic. It seems to have problems with building it at the moment and I've logged an issue with py2app. Basically it looks like this:

 File "/Users/user/.virtualenvs/jellyfin-desktop/lib/python3.8/site-packages/py2app/util.py", line 497, in byte_compile
    raise RuntimeError("Don't know how to handle %r" % mod.filename)
RuntimeError: Don't know how to handle '/Users/user/.virtualenvs/jellyfin-desktop/lib/python3.8/site-packages/pydantic/__init__'

and the two files inside the site-packages/pydantic folder are __init__.py and __init__.cpython38-darwin.so. If anyone has an idea of what I should do from here, that would be helpful

iwalton3 commented 3 years ago

Try looking at th CI job. You can make a pure-python build that doesn't need a compiled library.

I also only use it for config validation so I suppose it could be replaced.

brukberhane commented 3 years ago

@iwalton3 where do I find the CI job? I'm still pretty new to this. Or if you could give me an older commit that doesn't use pydantic, I'd like to try building on it.

iwalton3 commented 3 years ago

https://github.com/jellyfin/jellyfin-desktop/blob/a33bbc3f6e77e3f84945376862edfbed5d52ef6f/azure-pipelines.yml#L66

brukberhane commented 3 years ago

@iwalton3 that worked perfectly! So besides that, I've now encountered another error. Here is the traceback

2021-03-21 23:36:10,479 [   ERROR] menu: Could not load profile manager.
Traceback (most recent call last):
  File "jellyfin_mpv_shim/menu.pyc", line 79, in __init__
  File "jellyfin_mpv_shim/video_profile.pyc", line 61, in __init__
FileNotFoundError: Could not find default shader pack.
Traceback (most recent call last):
  File "/Users/user/projects/Python/jellyfin-desktop/dist/Jellyfin MPV Desktop.app/Contents/Resources/__boot__.py", line 411, in <module>
    _run()
  File "/Users/user/projects/Python/jellyfin-desktop/dist/Jellyfin MPV Desktop.app/Contents/Resources/__boot__.py", line 394, in _run
    exec(compile(source, path, "exec"), globals(), globals())
  File "/Users/user/projects/Python/jellyfin-desktop/dist/Jellyfin MPV Desktop.app/Contents/Resources/jellyfin-mpv-desktop", line 8, in <module>
    sys.exit(main_desktop())
  File "jellyfin_mpv_shim/mpv_shim.pyc", line 118, in main_desktop
  File "jellyfin_mpv_shim/mpv_shim.pyc", line 85, in main
  File "jellyfin_mpv_shim/webclient_view/__init__.pyc", line 152, in login_servers
  File "jellyfin_mpv_shim/clients.pyc", line 93, in try_connect
  File "jellyfin_mpv_shim/clients.pyc", line 75, in _connect_all
  File "jellyfin_mpv_shim/clients.pyc", line 201, in _connect_client
  File "jellyfin_mpv_shim/clients.pyc", line 63, in client_factory

EDIT: Seems like the blunder was mine. I accidentally deleted an import statement in `clients.py`
NameError: name 'JellyfinClient' is not defined

I'd like some help deciphering exactly why it can't find the JellyfinClient...

brukberhane commented 3 years ago

It seems like it's trying to get /index.html from the jellyfin server and the server is returning a 404 error. I could maybe change that to /web/index.html and it'll be less of a problem.

Sorry for spamming here with old problems but yeah I've finally managed to recreate @krodelabestiole's work. I'll keep working on it and see if I can make the webclient folder reference from static to dynamic. But on the bright side, at least it opens and works!

brukberhane commented 3 years ago

I've finally managed to change the static_folder value for the webclient to move around with the .app. So I guess I have a fully functional app now? Should I upload the code as a fork for testing? @iwalton3 let me know.

iwalton3 commented 3 years ago

Sure. I don't have a Mac so others will have to test it of course. My goal would be to get an Azure Pipelines job that builds a release like I have for Windows.