From 4438431aff952dcafbf65608e5a43a66a58d6fc8 Mon Sep 17 00:00:00 2001 From: Joel Takvorian Date: Sun, 7 Aug 2022 15:05:45 +0200 Subject: [PATCH 01/20] Do not show discovery menu when spotify is not used Fixes #856 --- src/js/components/Sidebar.js | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/js/components/Sidebar.js b/src/js/components/Sidebar.js index 2578bfec..73697a13 100755 --- a/src/js/components/Sidebar.js +++ b/src/js/components/Sidebar.js @@ -85,11 +85,11 @@ const Sidebar = () => { -
- - <I18n path="sidebar.discover" /> - - {spotify_available && ( + {spotify_available && ( +
+ + <I18n path="sidebar.discover" /> + { - )} - - - - - {spotify_available && ( + + + + - )} - - - - -
+ + + + +
+ )}
From cfca0b95d437f0f279663a9894c043c07f0df9bc Mon Sep 17 00:00:00 2001 From: Joel Takvorian <jtakvori@redhat.com> Date: Sun, 7 Aug 2022 15:49:57 +0200 Subject: [PATCH 02/20] Distinguish "missing spotify token" vs "spotify not enabled" --- src/js/components/Sidebar.js | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/js/components/Sidebar.js b/src/js/components/Sidebar.js index 73697a13..77bf3682 100755 --- a/src/js/components/Sidebar.js +++ b/src/js/components/Sidebar.js @@ -66,7 +66,8 @@ const StatusIcon = () => { const Sidebar = () => { const dispatch = useDispatch(); - const spotify_available = useSelector((state) => state.spotify.access_token); + const spotify_enabled = useSelector((state) => state.spotify.enabled); + const spotify_has_token = useSelector((state) => state.spotify.access_token); const close = () => dispatch(toggleSidebar(false)); @@ -85,27 +86,31 @@ const Sidebar = () => { </Link> </section> - {spotify_available && ( + {spotify_enabled && ( <section className="sidebar__menu__section"> <title className="sidebar__menu__section__title"> <I18n path="sidebar.discover" /> - - - - + {spotify_has_token && ( + + + + + )} - - - - + {spotify_has_token && ( + + + + + )} From 58ef7e6bea65ce6dd4a23a5f82702833f415b84a Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Sat, 3 Dec 2022 22:07:29 +1300 Subject: [PATCH 03/20] YTMusic playlist support - Can create and edit playlists - Can now load playlists natively --- src/js/services/core/actions.js | 51 +-- src/js/services/core/middleware.js | 4 +- src/js/services/mopidy/middleware.js | 173 +++------- src/js/services/spotify/actions.js | 8 +- src/js/util/selectors.js | 5 + src/js/views/Modals/CreatePlaylist.js | 12 + src/js/views/Modals/EditPlaylist.js | 468 ++++++++++---------------- src/js/views/Playlist.js | 27 +- 8 files changed, 263 insertions(+), 485 deletions(-) diff --git a/src/js/services/core/actions.js b/src/js/services/core/actions.js index e97e271d..914359a6 100755 --- a/src/js/services/core/actions.js +++ b/src/js/services/core/actions.js @@ -371,9 +371,7 @@ export function reorderPlaylistTracks(uri, indexes, insert_before, snapshot_id = insert_before, snapshot_id, }; - - case 'm3u': - case 'gmusic': + default: return { type: 'MOPIDY_REORDER_PLAYLIST_TRACKS', key: uri, @@ -381,40 +379,22 @@ export function reorderPlaylistTracks(uri, indexes, insert_before, snapshot_id = range_length: range.length, insert_before, }; - - default: - return { - type: 'UNSUPPORTED_ACTION', - name: 'reorderPlaylistTracks', - }; } } -export function savePlaylist(uri, name, description = '', is_public = false, is_collaborative = false, image = null) { +export function savePlaylist(uri, data) { switch (uriSource(uri)) { case 'spotify': return { type: 'SPOTIFY_SAVE_PLAYLIST', key: uri, - name, - description: (description == '' ? null : description), - image, - is_public, - is_collaborative, + data, }; - - case 'm3u': - case 'gmusic': + default: return { type: 'MOPIDY_SAVE_PLAYLIST', key: uri, - name, - }; - - default: - return { - type: 'UNSUPPORTED_ACTION', - name: 'savePlaylist', + data, }; } } @@ -432,7 +412,6 @@ export function deletePlaylist(uri) { switch (uriSource(uri)) { case 'spotify': return spotifyActions.following(uri, 'DELETE'); - default: return mopidyActions.deletePlaylist(uri); } @@ -446,20 +425,12 @@ export function removeTracksFromPlaylist(uri, tracks_indexes) { key: uri, tracks_indexes, }; - - case 'm3u': - case 'gmusic': + default: return { type: 'MOPIDY_REMOVE_PLAYLIST_TRACKS', key: uri, tracks_indexes, }; - - default: - return { - type: 'UNSUPPORTED_ACTION', - name: 'removeTracksFromPlaylist', - }; } } @@ -471,20 +442,12 @@ export function addTracksToPlaylist(uri, tracks_uris) { key: uri, tracks_uris, }; - - case 'm3u': - case 'gmusic': + default: return { type: 'MOPIDY_ADD_PLAYLIST_TRACKS', key: uri, tracks_uris, }; - - default: - return { - type: 'UNSUPPORTED_ACTION', - name: 'addTracksToPlaylist', - }; } } diff --git a/src/js/services/core/middleware.js b/src/js/services/core/middleware.js index be1a4b6b..2fe79c2f 100755 --- a/src/js/services/core/middleware.js +++ b/src/js/services/core/middleware.js @@ -275,10 +275,8 @@ const CoreMiddleware = (function () { case 'spotify': store.dispatch(spotifyActions.getPlaylist(key, {})); break; - case 'm3u': - store.dispatch(mopidyActions.getPlaylist(key, {})); - break; default: + store.dispatch(mopidyActions.getPlaylist(key, {})); break; } next(action); diff --git a/src/js/services/mopidy/middleware.js b/src/js/services/mopidy/middleware.js index 227f094c..621ed765 100755 --- a/src/js/services/mopidy/middleware.js +++ b/src/js/services/mopidy/middleware.js @@ -1423,7 +1423,7 @@ const MopidyMiddleware = (function () { // requires a Mopidy playlist object (with updates) request(store, 'playlists.lookup', { uri: action.key }) .then((response) => { - const mopidy_playlist = { ...response, name: action.name }; + const mopidy_playlist = { ...response, ...action.data }; request(store, 'playlists.save', { playlist: mopidy_playlist }) .then((response) => { @@ -1432,9 +1432,9 @@ const MopidyMiddleware = (function () { // Overwrite our playlist with the response to our save // This is essential to get the updated URI from Mopidy const playlist = { + ...action.data, ...store.getState().core.items[action.key], - uri: response.uri, - name: response.name, + ...response, }; // When we rename a playlist, the URI also changes to reflect the name change. @@ -2154,134 +2154,57 @@ const MopidyMiddleware = (function () { case 'MOPIDY_GET_LIBRARY_PLAYLISTS': { store.dispatch(uiActions.startProcess(action.type, { notification: false })); - // Built-in playlist support works differently to other providers - if (action.uri === 'm3u:playlists') { - request(store, 'playlists.asList') - .then((listResponse) => { - const libraryPlaylists = []; - const playlist_uris = arrayOf('uri', listResponse).filter( - (pUri) => (pUri.indexOf('m3u') > -1), - ); - store.dispatch( - uiActions.updateProcess( - action.type, - { - total: playlist_uris.length, - remaining: playlist_uris.length, - }, - ), - ); + request(store, 'playlists.asList').then((browseResponse) => { + const allUris = arrayOf('uri', browseResponse); + store.dispatch( + uiActions.updateProcess( + action.type, + { + total: allUris.length, + remaining: allUris.length, + }, + ), + ); - if (playlist_uris.length) { - playlist_uris.forEach((uri, index) => { - request(store, 'playlists.lookup', { uri }) - .then((response) => { - if (response) { - libraryPlaylists.push( - formatPlaylist({ - name: response.name, - uri: response.uri, - can_edit: uriSource(response.uri) === 'm3u', - last_modified: response.last_modified, - // By not including actual tracks they will be fetched when needed. We don't - // want these simple tracks because they don't contain duration, artist, etc. - tracks_total: response.tracks ? response.tracks.length : null, - }), - ); - } + const run = () => { + if (allUris.length) { + const uri = allUris.splice(0, 1)[0]; + const processor = store.getState().ui.processes[action.type]; - store.dispatch( - uiActions.updateProcess( - action.type, - { - remaining: playlist_uris.length - index - 1, - }, - ), - ); - - if (index === playlist_uris.length - 1) { - store.dispatch(coreActions.itemsLoaded(libraryPlaylists)); - store.dispatch(coreActions.libraryLoaded({ - uri: action.uri, - type: 'playlists', - items_uris: arrayOf('uri', libraryPlaylists), - })); - store.dispatch(uiActions.processFinished(action.type)); - } - }); - }); - } else { - store.dispatch(coreActions.libraryLoaded({ - uri: action.uri, - type: 'playlists', - items_uris: [], - })); - store.dispatch(uiActions.stopLoading('mopidy:library:playlists')); - store.dispatch(uiActions.processFinished(action.type)); + if (processor && processor.status === 'cancelling') { + store.dispatch(uiActions.processCancelled(action.type)); + store.dispatch(uiActions.stopLoading(action.uri)); + return; } - }); - } else { - request(store, 'library.browse', { uri: action.uri }) - .then((browseResponse) => { - const libraryPlaylists = []; + store.dispatch(uiActions.updateProcess(action.type, { remaining: allUris.length })); - store.dispatch( - uiActions.updateProcess( - action.type, - { - total: browseResponse.length, - remaining: browseResponse.length, - }, - ), - ); + request(store, 'playlists.lookup', { uri }).then((lookupResponse) => { + if (lookupResponse) { + const playlist = formatPlaylist({ + name: lookupResponse.name, + uri: lookupResponse.uri, + can_edit: true, // TODO: Confirm whether some are uneditable?? + last_modified: lookupResponse.last_modified, + // Don't include simple tracks; they don't contain duration, artist, etc. + tracks_total: lookupResponse?.tracks?.length || null, + }); - if (browseResponse.length) { - browseResponse.forEach((playlist, index) => { - request(store, 'library.lookup', { uris: [playlist.uri] }) - .then((response) => { - if (response) { - libraryPlaylists.push( - formatPlaylist({ - name: playlist.name, - uri: playlist.uri, - can_edit: uriSource(playlist.uri) === 'm3u', - last_modified: playlist.last_modified, - tracks: formatTracks(response[playlist.uri]), - }), - ); - } + store.dispatch(coreActions.itemLoaded(playlist)); + } + run(); + }); + } else { + store.dispatch(uiActions.processFinished(action.type)); + store.dispatch(coreActions.libraryLoaded({ + uri: action.uri, + type: 'playlists', + items_uris: arrayOf('uri', browseResponse), + })); + } + }; - store.dispatch( - uiActions.updateProcess( - action.type, - { - remaining: browseResponse.length - index - 1, - }, - ), - ); - - if (index === browseResponse.length - 1) { - store.dispatch(coreActions.itemsLoaded(libraryPlaylists)); - store.dispatch(coreActions.libraryLoaded({ - uri: action.uri, - type: 'playlists', - items_uris: arrayOf('uri', libraryPlaylists), - })); - store.dispatch(uiActions.processFinished(action.type)); - } - }); - }); - } else { - store.dispatch(coreActions.libraryLoaded({ - uri: action.uri, - type: 'playlists', - items_uris: [], - })); - store.dispatch(uiActions.stopLoading('mopidy:library:playlists')); - store.dispatch(uiActions.processFinished(action.type)); - } - }); - } + run(); + }); break; } diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js index 474601fe..be9a269d 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -1237,14 +1237,8 @@ export function createPlaylist(playlist) { }; } -export function savePlaylist(uri, name, description, is_public, is_collaborative, image) { +export function savePlaylist(uri, { image, ...data }) { return (dispatch, getState) => { - const data = { - name, - description, - public: is_public, - collaborative: is_collaborative, - }; const { spotify: { me: { diff --git a/src/js/util/selectors.js b/src/js/util/selectors.js index 933cd9d2..03782f69 100755 --- a/src/js/util/selectors.js +++ b/src/js/util/selectors.js @@ -121,6 +121,11 @@ const providers = { uri: 'jellyfin:playlists', title: i18n('services.jellyfin.title'), }, + { + scheme: 'ytmusic:', + uri: 'ytmusic:playlists', + title: i18n('services.youtube.title'), + }, ], albums: [ { diff --git a/src/js/views/Modals/CreatePlaylist.js b/src/js/views/Modals/CreatePlaylist.js index 114f2365..109cc27b 100755 --- a/src/js/views/Modals/CreatePlaylist.js +++ b/src/js/views/Modals/CreatePlaylist.js @@ -154,6 +154,18 @@ const CreatePlaylist = () => { +
diff --git a/src/js/services/mopidy/middleware.js b/src/js/services/mopidy/middleware.js index 621ed765..ab929bd6 100755 --- a/src/js/services/mopidy/middleware.js +++ b/src/js/services/mopidy/middleware.js @@ -860,7 +860,6 @@ const MopidyMiddleware = (function () { break; case 'MOPIDY_PLAY_PLAYLIST': { - console.debug(action) const playlist = store.getState().core.items[action.uri]; const { sortField, sortReverse } = getSortSelector(store.getState(), 'playlist_tracks'); if (playlist && playlist.tracks) { @@ -2153,22 +2152,25 @@ const MopidyMiddleware = (function () { } case 'MOPIDY_GET_LIBRARY_PLAYLISTS': { store.dispatch(uiActions.startProcess(action.type, { notification: false })); + const scheme = action.uri.split(':')[0]; request(store, 'playlists.asList').then((browseResponse) => { - const allUris = arrayOf('uri', browseResponse); + const allUris = arrayOf('uri', browseResponse).filter((uri) => uri.startsWith(scheme)); + const unloadedUris = [...allUris]; + store.dispatch( uiActions.updateProcess( action.type, { total: allUris.length, - remaining: allUris.length, + remaining: unloadedUris.length, }, ), ); const run = () => { - if (allUris.length) { - const uri = allUris.splice(0, 1)[0]; + if (unloadedUris.length) { + const uri = unloadedUris.splice(0, 1)[0]; const processor = store.getState().ui.processes[action.type]; if (processor && processor.status === 'cancelling') { @@ -2176,7 +2178,7 @@ const MopidyMiddleware = (function () { store.dispatch(uiActions.stopLoading(action.uri)); return; } - store.dispatch(uiActions.updateProcess(action.type, { remaining: allUris.length })); + store.dispatch(uiActions.updateProcess(action.type, { remaining: unloadedUris.length })); request(store, 'playlists.lookup', { uri }).then((lookupResponse) => { if (lookupResponse) { @@ -2198,7 +2200,7 @@ const MopidyMiddleware = (function () { store.dispatch(coreActions.libraryLoaded({ uri: action.uri, type: 'playlists', - items_uris: arrayOf('uri', browseResponse), + items_uris: allUris, })); } }; From 179089f41bd41a623e9fea217deafd6d79dd7fd0 Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Sun, 11 Dec 2022 20:41:45 +1300 Subject: [PATCH 05/20] Updating to GST-HACK for Spotify playback support --- Dockerfile | 159 ++++++++++++++++++++++++++----------- docker-compose.example.yml | 1 + docker/requirements.txt | 9 +++ 3 files changed, 123 insertions(+), 46 deletions(-) mode change 100755 => 100644 Dockerfile create mode 100644 docker/requirements.txt diff --git a/Dockerfile b/Dockerfile old mode 100755 new mode 100644 index 983170fb..89930082 --- a/Dockerfile +++ b/Dockerfile @@ -1,46 +1,109 @@ -FROM debian:buster +FROM rust:slim-bullseye +LABEL org.opencontainers.image.authors="https://github.com/seppi91" +ARG TARGETPLATFORM +ARG TARGETARCH +ARG TARGETVARIANT +RUN printf "I'm building for TARGETPLATFORM=${TARGETPLATFORM}" \ + && printf ", TARGETARCH=${TARGETARCH}" \ + && printf ", TARGETVARIANT=${TARGETVARIANT} \n" \ + && printf "With uname -s : " && uname -s \ + && printf "and uname -m : " && uname -mm # Switch to the root user while we do our changes USER root -# Install GStreamer and other required Debian packages +# Install all libraries and needs RUN apt-get update \ - && apt-get install -y --no-install-recommends \ + && apt-get install -y --no-install-recommends \ + sudo \ + build-essential \ + curl \ + git \ wget \ gnupg2 \ - git \ - python3-setuptools \ - python3-pip \ + tar \ dumb-init \ graphviz-dev \ - gstreamer1.0-plugins-bad \ - gstreamer1.0-plugins-good \ - gstreamer1.0-plugins-ugly \ - gstreamer1.0-pulseaudio \ + pulseaudio \ libasound2-dev \ - python3-dev \ - python3-gst-1.0 \ - build-essential \ libdbus-glib-1-dev \ libgirepository1.0-dev \ + # DLNA Server dleyna-server \ - sudo \ - && rm -rf /var/lib/apt/lists/* + # Install Python + python3-dev \ + python3-gst-1.0 \ + python3-setuptools \ + python3-pip \ + python3-venv \ + # GStreamer (Plugins) + libgstreamer1.0-dev \ + libgstreamer-plugins-base1.0-dev \ + libgstreamer-plugins-bad1.0-dev \ + libgstrtspserver-1.0-dev \ + gstreamer1.0-plugins-base \ + gstreamer1.0-plugins-good \ + gstreamer1.0-plugins-bad \ + gstreamer1.0-plugins-ugly \ + gstreamer1.0-libav \ + #gstreamer1.0-alsa \ + gstreamer1.0-pulseaudio \ + # GStreamer build dependencies see + # https://github.com/Kynothon/gst-plugins-rs-docker/blob/master/XDockerfile + llvm-dev \ + libclang-dev \ + clang \ + gcc \ + libssl-dev \ + libcsound64-dev \ + libpango1.0-dev \ + libdav1d-dev \ + libwebp-dev + # libgtk-4-dev # Only in bookworm -# Install libspotify-dev from apt.mopidy.com +# Install gstreamer-spotify (EXPERIMENTAL) +# Note: For spotify with upgraded version number of dependency librespot to 0.4.2 +#RUN cargo install cargo-c +WORKDIR /build +RUN git clone --depth 1 --single-branch -b main https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git +WORKDIR /build/gst-plugins-rs +RUN sed -i 's/librespot = { version = "0.4", default-features = false }/librespot = { version = "0.4.2", default-features = false }/g' audio/spotify/Cargo.toml +RUN MULTIARCHTUPLE=$(dpkg-architecture -qDEB_HOST_MULTIARCH) \ + #&& cargo cbuild --no-default-features -p gst-plugin-spotify --prefix=/usr --libdir=/usr/lib/$MULTIARCHTUPLE/ -r \ + #&& cargo cinstall -p gst-plugin-spotify --prefix=/usr --libdir=/usr/lib/$MULTIARCHTUPLE/ + && cargo build --no-default-features -p gst-plugin-spotify -r \ + && cp ./target/release/libgstspotify.so /usr/lib/$MULTIARCHTUPLE/gstreamer-1.0/ + #&& ln -s /usr/lib/$MULTIARCHTUPLE/gstreamer-1.0/libgstspotify.so /usr/lib64/$MULTIARCHTUPLE/gstreamer-1.0/libgstspotify.so || true \ +WORKDIR /build +RUN rm -rf gst-plugins-rs +WORKDIR / + +# Install mopidy from apt.mopidy.com +# see https://docs.mopidy.com/en/latest/installation/debian/ RUN mkdir -p /usr/local/share/keyrings \ - && wget -q -O /usr/local/share/keyrings/mopidy-archive-keyring.gpg https://apt.mopidy.com/mopidy.gpg \ - && wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/buster.list \ - && apt-get update \ - && apt-get install -y libspotify-dev mopidy-spotify \ - && rm -rf /var/lib/apt/lists/* + && wget -q -O /usr/local/share/keyrings/mopidy-archive-keyring.gpg https://apt.mopidy.com/mopidy.gpg \ + && wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/buster.list \ + && apt-get update \ + && apt-get install -y mopidy \ + && rm -rf /var/lib/apt/lists/* -# Clone Iris from the repository and install in development mode. -# This allows a binding at "/iris" to map to your local folder for development, rather than -# installing using pip. -# Note using ADD helps prevent caching issues. When HEAD changes, our cache is invalidated, whee! +# Upgrade Python package manager pip +# https://pypi.org/project/pip/ +RUN python3 -m pip install --upgrade pip + +# Install PyGObject +# https://pypi.org/project/PyGObject/ +RUN python3 -m pip install pygobject + +# Install cffi from source +# Note: In some distributions libffi-devel is too old, hardcoded stuff +# https://pypi.org/project/cffi/ +RUN python3 -m pip install cffi + +# Install Iris +# Note: ADD helps prevent RUN caching issues. When HEAD changes in repo, our cache will be invalidated! ADD https://api.github.com/repos/jaedb/Iris/git/refs/heads/master version.json -RUN git clone --depth 1 -b master https://github.com/jaedb/Iris.git /iris \ +RUN git clone --depth 1 --single-branch -b master https://github.com/jaedb/Iris.git /iris \ && cd /iris \ && python3 setup.py develop \ && mkdir -p /var/lib/mopidy/.config \ @@ -48,33 +111,37 @@ RUN git clone --depth 1 -b master https://github.com/jaedb/Iris.git /iris \ # Allow mopidy user to run system commands (restart, local scan, etc) && echo "mopidy ALL=NOPASSWD: /iris/mopidy_iris/system.sh" >> /etc/sudoers -# Install additional Python dependencies -RUN python3 -m pip install --no-cache \ - tox \ - mopidy-mpd \ - mopidy-local - -# Start helper script. -COPY docker/entrypoint.sh /entrypoint.sh - -# Default configuration. -COPY docker/mopidy/mopidy.example.conf /config/mopidy.conf - -# Copy the pulse-client configuratrion. -COPY docker/mopidy/pulse-client.conf /etc/pulse/client.conf - -# Add version info to image COPY VERSION / +COPY mopidy_iris/ /iris/mopidy_iris +COPY docker/mopidy/mopidy.example.conf /config/mopidy.conf +COPY docker/mopidy/pulse-client.conf /etc/pulse/client.conf +RUN echo "1" >> /IS_CONTAINER + +# Install mopidy-spotify-gstspotify (Hack, not released yet!) +# (https://github.com/kingosticks/mopidy-spotify/tree/gstspotifysrc-hack) +RUN git clone --depth 1 -b gstspotifysrc-hack https://github.com/kingosticks/mopidy-spotify.git mopidy-spotify \ + && cd mopidy-spotify \ + && python3 setup.py install \ + && cd .. \ + && rm -rf mopidy-spotify + +# Install additional Python dependencies +COPY docker/requirements.txt . +RUN python3 -m pip install -r requirements.txt + +# Cleanup +RUN apt-get clean all && rm -rf /var/lib/apt/lists/* && rm -rf /root/.cache + +COPY docker/entrypoint.sh /entrypoint.sh # Allows any user to run mopidy, but runs by default as a randomly generated UID/GID. # RUN useradd -ms /bin/bash mopidy ENV HOME=/var/lib/mopidy RUN set -ex \ - && usermod -G audio,sudo mopidy \ + && usermod -G audio,sudo,pulse-access mopidy \ && mkdir /var/lib/mopidy/local \ - && chown mopidy:audio -R $HOME /entrypoint.sh /iris \ - && chmod go+rwx -R $HOME /entrypoint.sh /iris \ - && echo "1" >> /IS_CONTAINER + && chown mopidy:audio -R $HOME /entrypoint.sh \ + && chmod go+rwx -R $HOME /entrypoint.sh # Runs as mopidy user by default. USER mopidy:audio diff --git a/docker-compose.example.yml b/docker-compose.example.yml index 82aaadb3..3d703863 100755 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -23,6 +23,7 @@ services: - 6600:6600 - 6680:6680 volumes: + # - ./mopidy/iris:/iris/mopidy/iris # To use a locally-built UI - ./docker/mopidy/iris:/var/lib/mopidy/iris # Iris-specific storage - ./docker/mopidy/m3u:/var/lib/mopidy/m3u # To persist local playlists - ./docker/mopidy/mopidy.conf:/config/mopidy.conf diff --git a/docker/requirements.txt b/docker/requirements.txt new file mode 100644 index 00000000..3be2d1a1 --- /dev/null +++ b/docker/requirements.txt @@ -0,0 +1,9 @@ +Mopidy-Local +Mopidy-Mpd +Mopidy-MusicBox-Webclient +Mopidy-Soundcloud +Mopidy-Youtube +Mopidy-YTMusic +ytmusicapi +youtube_dl +tox \ No newline at end of file From 11f202a9b7fbee543634b9548ec2f83555ab1c58 Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Sun, 11 Dec 2022 20:42:01 +1300 Subject: [PATCH 06/20] Removing duplicate playlist groups --- src/js/services/mopidy/middleware.js | 4 ++-- src/js/services/spotify/actions.js | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/js/services/mopidy/middleware.js b/src/js/services/mopidy/middleware.js index ab929bd6..91fd4f00 100755 --- a/src/js/services/mopidy/middleware.js +++ b/src/js/services/mopidy/middleware.js @@ -1,7 +1,7 @@ import ReactGA from 'react-ga'; import Mopidy from 'mopidy'; import { sha256 } from 'js-sha256'; -import { sampleSize, compact, chunk, find } from 'lodash'; +import { sampleSize, compact, chunk, find, uniq } from 'lodash'; import { i18n } from '../../locale'; import { generateGuid, @@ -2096,7 +2096,7 @@ const MopidyMiddleware = (function () { ...item, images: [], // Images is a playlist dependency, so this prevents triggering full load })); - const playlists_uris = arrayOf('uri', playlists); + const playlists_uris = uniq(arrayOf('uri', playlists)); const allUris = [...playlists_uris]; store.dispatch(coreActions.itemLoaded({ ...playlistGroup, diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js index be9a269d..66a73519 100755 --- a/src/js/services/spotify/actions.js +++ b/src/js/services/spotify/actions.js @@ -1,4 +1,5 @@ import React from 'react'; +import { uniq } from 'lodash'; import { arrayOf } from '../../util/arrays'; import { generateGuid, @@ -506,13 +507,16 @@ export function getMood(uri, { forceRefetch } = {}) { getState, endpoint: plEndpoint, }).then((response) => { - playlists = [...playlists, ...formatPlaylists(response.playlists.items)]; + playlists = [ + ...playlists, + ...formatPlaylists(response.playlists.items.filter((item) => item)), + ]; if (response.playlists.next) { fetchPlaylists(response.playlists.next); } else { dispatch(coreActions.itemLoaded({ ...playlistGroup, - playlists_uris: arrayOf('uri', playlists), + playlists_uris: uniq(arrayOf('uri', playlists)), })); dispatch(coreActions.itemsLoaded(playlists)); dispatch(uiActions.stopLoading(loaderId)); From 87fd816335e7a8df1d98452e52950bca411c872a Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Mon, 2 Jan 2023 21:42:34 +1300 Subject: [PATCH 07/20] Source icon top-left - Matches Spotify artwork, which we hide when it is burned-in on the image - Consistent across all providers now --- src/scss/components/_grid.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scss/components/_grid.scss b/src/scss/components/_grid.scss index 899c3092..ab544217 100755 --- a/src/scss/components/_grid.scss +++ b/src/scss/components/_grid.scss @@ -59,7 +59,7 @@ .source { position: absolute; top: 10px; - right: 10px; + left: 10px; padding: 0; font-size: 1.5rem; From a0aaada0c89c122ab1e18171999037334bc05f2a Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Mon, 2 Jan 2023 21:43:45 +1300 Subject: [PATCH 08/20] Dockerfile to *build* assets manually - Cannot safely (and consistently) overwrite PIP-installed package with host volume binding, so is easier to build within Docker - Add `.nvmrc` for consistent buildout --- .nvmrc | 1 + Dockerfile | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 .nvmrc diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000..ca3f1e5c --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v14 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 89930082..ad485f1a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -61,6 +61,10 @@ RUN apt-get update \ libwebp-dev # libgtk-4-dev # Only in bookworm +# Install Node, to build Iris JS application +RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash - && \ + apt-get install -y nodejs + # Install gstreamer-spotify (EXPERIMENTAL) # Note: For spotify with upgraded version number of dependency librespot to 0.4.2 #RUN cargo install cargo-c @@ -105,6 +109,7 @@ RUN python3 -m pip install cffi ADD https://api.github.com/repos/jaedb/Iris/git/refs/heads/master version.json RUN git clone --depth 1 --single-branch -b master https://github.com/jaedb/Iris.git /iris \ && cd /iris \ + && npm run prod \ && python3 setup.py develop \ && mkdir -p /var/lib/mopidy/.config \ && ln -s /config /var/lib/mopidy/.config/mopidy \ From 3bc1ea0bb3c31ee1386de312661e4d0d08658aba Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Mon, 2 Jan 2023 21:58:32 +1300 Subject: [PATCH 09/20] Build Docker image for any push to develop or master --- .github/workflows/ci.yml | 13 +++++++++++-- MANIFEST.in | 3 ++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3a4d5f0..332ac3bd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -127,7 +127,7 @@ jobs: name: 'Publish: DockerHub' runs-on: ubuntu-latest needs: [jest, tox] - if: github.event_name == 'release' + if: github.event_name == 'release' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master' steps: - name: Set up QEMU uses: docker/setup-qemu-action@v1 @@ -135,7 +135,8 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - - name: Generating tags and labels + - name: Generating release tags and labels + if: github.event_name == 'release' id: meta uses: docker/metadata-action@v4 with: @@ -145,6 +146,14 @@ jobs: type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} + - name: Generating branch labels + if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master' + id: meta + uses: docker/metadata-action@v4 + with: + images: jaedb/iris + tags: ${{ github.ref##*/ }} + - name: Login to DockerHub uses: docker/login-action@v1 with: diff --git a/MANIFEST.in b/MANIFEST.in index 7a512fc1..0957ae8a 100755 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -15,4 +15,5 @@ recursive-exclude src * recursive-exclude docker * exclude .jshintrc exclude .babelrc -exclude jest.config.js \ No newline at end of file +exclude jest.config.js +exclude .nvmrc \ No newline at end of file From a5b5ca0ced8c17d712f10af14dc0b7e704ef49d9 Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Mon, 2 Jan 2023 22:00:55 +1300 Subject: [PATCH 10/20] Using GITHUB_REF_NAME --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 332ac3bd..24e4558c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,7 +152,7 @@ jobs: uses: docker/metadata-action@v4 with: images: jaedb/iris - tags: ${{ github.ref##*/ }} + tags: ${{ GITHUB_REF_NAME }} - name: Login to DockerHub uses: docker/login-action@v1 From 8c4b166c06e9ac04242ea798cdeea73acf6f16e0 Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Mon, 2 Jan 2023 22:04:08 +1300 Subject: [PATCH 11/20] No wrapping, just leading $ --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 24e4558c..323cc68d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,7 +152,7 @@ jobs: uses: docker/metadata-action@v4 with: images: jaedb/iris - tags: ${{ GITHUB_REF_NAME }} + tags: $GITHUB_REF_NAME - name: Login to DockerHub uses: docker/login-action@v1 From b5f9baa17d0961ae20a7786a479fcdc76c0ed95f Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Mon, 2 Jan 2023 22:06:27 +1300 Subject: [PATCH 12/20] Separating meta for release vs edge --- .github/workflows/ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 323cc68d..7587cf49 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -137,7 +137,7 @@ jobs: - name: Generating release tags and labels if: github.event_name == 'release' - id: meta + id: release_meta uses: docker/metadata-action@v4 with: images: jaedb/iris @@ -146,9 +146,9 @@ jobs: type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} - - name: Generating branch labels + - name: Generating edge branch labels if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master' - id: meta + id: edge_meta uses: docker/metadata-action@v4 with: images: jaedb/iris @@ -164,5 +164,5 @@ jobs: uses: docker/build-push-action@v2 with: push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + tags: ${{ steps.release_meta.outputs.tags || steps.edge_meta.outputs.tags }} + labels: ${{ steps.release_meta.outputs.labels || steps.edge_meta.outputs.tags }} From 3a1f43870bb814f948b9eacc462bc727b2e28340 Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Mon, 2 Jan 2023 22:15:32 +1300 Subject: [PATCH 13/20] Double-brackets --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7587cf49..4b982f71 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,7 +152,7 @@ jobs: uses: docker/metadata-action@v4 with: images: jaedb/iris - tags: $GITHUB_REF_NAME + tags: ${{GITHUB_REF_NAME}} - name: Login to DockerHub uses: docker/login-action@v1 From 7fb68a32a84cedcd1430680487250a17de8c167c Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Mon, 2 Jan 2023 22:17:38 +1300 Subject: [PATCH 14/20] github.ref --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b982f71..4790a73d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,7 +152,7 @@ jobs: uses: docker/metadata-action@v4 with: images: jaedb/iris - tags: ${{GITHUB_REF_NAME}} + tags: ${{ github.ref }} - name: Login to DockerHub uses: docker/login-action@v1 From 0eb30a92875eee4147e28b3e01c9e88ecf6800b4 Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Mon, 2 Jan 2023 22:20:39 +1300 Subject: [PATCH 15/20] New step to extract branch name --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4790a73d..4d1a2a51 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -135,6 +135,11 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 + - name: Extract branch name + shell: bash + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" + id: extract_branch + - name: Generating release tags and labels if: github.event_name == 'release' id: release_meta @@ -152,7 +157,7 @@ jobs: uses: docker/metadata-action@v4 with: images: jaedb/iris - tags: ${{ github.ref }} + tags: ${{ steps.extract_branch.outputs.branch }} - name: Login to DockerHub uses: docker/login-action@v1 From c0f5229af1bc733c3139c0d671390ccd1aaff1fd Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Tue, 3 Jan 2023 08:01:14 +1300 Subject: [PATCH 16/20] Dockerfile installing nodejs and building frontend - Need to experiment with file size reduction --- Dockerfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ad485f1a..52decb25 100644 --- a/Dockerfile +++ b/Dockerfile @@ -109,6 +109,7 @@ RUN python3 -m pip install cffi ADD https://api.github.com/repos/jaedb/Iris/git/refs/heads/master version.json RUN git clone --depth 1 --single-branch -b master https://github.com/jaedb/Iris.git /iris \ && cd /iris \ + && npm install \ && npm run prod \ && python3 setup.py develop \ && mkdir -p /var/lib/mopidy/.config \ @@ -135,7 +136,10 @@ COPY docker/requirements.txt . RUN python3 -m pip install -r requirements.txt # Cleanup -RUN apt-get clean all && rm -rf /var/lib/apt/lists/* && rm -rf /root/.cache +RUN apt-get clean all \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /root/.cache \ + && rm -rf /iris/node_modules COPY docker/entrypoint.sh /entrypoint.sh From 3286376c89d06ae374946700bbd3288a84947a94 Mon Sep 17 00:00:00 2001 From: jojo141185 Date: Tue, 3 Jan 2023 18:59:37 +0100 Subject: [PATCH 17/20] Updated Dockerfile with multi-stage build approach Moved the build process of the GStreamer plugins to a separate stage. Restructured the file a bit and cleaned up some unused dependencies. --- Dockerfile | 145 +++++++++++++++++++++++++++++------------------------ 1 file changed, 80 insertions(+), 65 deletions(-) diff --git a/Dockerfile b/Dockerfile index 52decb25..4ab21825 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,11 @@ -FROM rust:slim-bullseye +# --- Build Node --- +FROM rust:slim-bullseye AS Builder LABEL org.opencontainers.image.authors="https://github.com/seppi91" ARG TARGETPLATFORM ARG TARGETARCH ARG TARGETVARIANT + +# Print Info about current build Target RUN printf "I'm building for TARGETPLATFORM=${TARGETPLATFORM}" \ && printf ", TARGETARCH=${TARGETARCH}" \ && printf ", TARGETVARIANT=${TARGETVARIANT} \n" \ @@ -13,6 +16,52 @@ RUN printf "I'm building for TARGETPLATFORM=${TARGETPLATFORM}" \ USER root # Install all libraries and needs +RUN apt update \ + && apt install -yq --no-install-recommends \ + git \ + patch \ + libgstreamer-plugins-base1.0-dev \ + libgstreamer1.0-dev \ + libcsound64-dev \ + libclang-11-dev \ + libpango1.0-dev \ + libdav1d-dev \ + # libgtk-4-dev \ Only in bookworm + && rm -rf /var/lib/apt/lists/* + +WORKDIR /usr/src/gst-plugins-rs + +# Clone source of gst-plugins-rs to workdir +ARG GST_PLUGINS_RS_TAG=main +RUN git clone -c advice.detachedHead=false \ + --single-branch --depth 1 \ + --branch ${GST_PLUGINS_RS_TAG} \ + https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git ./ +# EXPERIMENTAL: For gstreamer-spotify set upgraded version number of dependency librespot to 0.4.2 +RUN sed -i 's/librespot = { version = "0.4", default-features = false }/librespot = { version = "0.4.2", default-features = false }/g' audio/spotify/Cargo.toml + +# Build GStreamer plugins written in Rust (optional with --no-default-features) +ENV DEST_DIR /target/gst-plugins-rs +ENV CARGO_PROFILE_RELEASE_DEBUG false +RUN export CSOUND_LIB_DIR="/usr/lib/$(uname -m)-linux-gnu" \ + && export PLUGINS_DIR=$(pkg-config --variable=pluginsdir gstreamer-1.0) \ + && export SO_SUFFIX=so \ + && cargo build --release --no-default-features \ + # List of packages to build + --package gst-plugin-spotify \ + # Use install command to create directory (-d), copy and print filenames (-v), and set attributes/permissions (-m) + && install -v -d ${DEST_DIR}/${PLUGINS_DIR} \ + && install -v -m 755 target/release/*.${SO_SUFFIX} ${DEST_DIR}/${PLUGINS_DIR} + + +# --- Release Node --- +FROM debian:bullseye-slim as Release + +# Switch to the root user while we do our changes +USER root +WORKDIR / + +# Install GStreamer and other required Debian packages RUN apt-get update \ && apt-get install -y --no-install-recommends \ sudo \ @@ -21,93 +70,54 @@ RUN apt-get update \ git \ wget \ gnupg2 \ - tar \ dumb-init \ graphviz-dev \ pulseaudio \ libasound2-dev \ libdbus-glib-1-dev \ libgirepository1.0-dev \ - # DLNA Server - dleyna-server \ # Install Python python3-dev \ python3-gst-1.0 \ python3-setuptools \ python3-pip \ - python3-venv \ # GStreamer (Plugins) - libgstreamer1.0-dev \ - libgstreamer-plugins-base1.0-dev \ - libgstreamer-plugins-bad1.0-dev \ - libgstrtspserver-1.0-dev \ - gstreamer1.0-plugins-base \ gstreamer1.0-plugins-good \ - gstreamer1.0-plugins-bad \ + gstreamer1.0-plugins-bad \ gstreamer1.0-plugins-ugly \ gstreamer1.0-libav \ - #gstreamer1.0-alsa \ gstreamer1.0-pulseaudio \ - # GStreamer build dependencies see - # https://github.com/Kynothon/gst-plugins-rs-docker/blob/master/XDockerfile - llvm-dev \ - libclang-dev \ - clang \ - gcc \ - libssl-dev \ - libcsound64-dev \ - libpango1.0-dev \ - libdav1d-dev \ - libwebp-dev - # libgtk-4-dev # Only in bookworm + && rm -rf /var/lib/apt/lists/* + +# Copy builded target data from Builder DEST_DIR to root +# Note: target directory tree links directly to $GST_PLUGIN_PATH +COPY --from=Builder /target/gst-plugins-rs/ / # Install Node, to build Iris JS application RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash - && \ apt-get install -y nodejs -# Install gstreamer-spotify (EXPERIMENTAL) -# Note: For spotify with upgraded version number of dependency librespot to 0.4.2 -#RUN cargo install cargo-c -WORKDIR /build -RUN git clone --depth 1 --single-branch -b main https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git -WORKDIR /build/gst-plugins-rs -RUN sed -i 's/librespot = { version = "0.4", default-features = false }/librespot = { version = "0.4.2", default-features = false }/g' audio/spotify/Cargo.toml -RUN MULTIARCHTUPLE=$(dpkg-architecture -qDEB_HOST_MULTIARCH) \ - #&& cargo cbuild --no-default-features -p gst-plugin-spotify --prefix=/usr --libdir=/usr/lib/$MULTIARCHTUPLE/ -r \ - #&& cargo cinstall -p gst-plugin-spotify --prefix=/usr --libdir=/usr/lib/$MULTIARCHTUPLE/ - && cargo build --no-default-features -p gst-plugin-spotify -r \ - && cp ./target/release/libgstspotify.so /usr/lib/$MULTIARCHTUPLE/gstreamer-1.0/ - #&& ln -s /usr/lib/$MULTIARCHTUPLE/gstreamer-1.0/libgstspotify.so /usr/lib64/$MULTIARCHTUPLE/gstreamer-1.0/libgstspotify.so || true \ -WORKDIR /build -RUN rm -rf gst-plugins-rs -WORKDIR / - -# Install mopidy from apt.mopidy.com +# Install mopidy and (optional) DLNA-server dleyna from apt.mopidy.com # see https://docs.mopidy.com/en/latest/installation/debian/ RUN mkdir -p /usr/local/share/keyrings \ && wget -q -O /usr/local/share/keyrings/mopidy-archive-keyring.gpg https://apt.mopidy.com/mopidy.gpg \ && wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/buster.list \ && apt-get update \ - && apt-get install -y mopidy \ + && apt-get install -y \ + mopidy \ && rm -rf /var/lib/apt/lists/* # Upgrade Python package manager pip # https://pypi.org/project/pip/ RUN python3 -m pip install --upgrade pip -# Install PyGObject -# https://pypi.org/project/PyGObject/ -RUN python3 -m pip install pygobject - -# Install cffi from source -# Note: In some distributions libffi-devel is too old, hardcoded stuff -# https://pypi.org/project/cffi/ -RUN python3 -m pip install cffi - -# Install Iris +# Clone Iris from the repository and install in development mode. +# This allows a binding at "/iris" to map to your local folder for development, rather than +# installing using pip. # Note: ADD helps prevent RUN caching issues. When HEAD changes in repo, our cache will be invalidated! ADD https://api.github.com/repos/jaedb/Iris/git/refs/heads/master version.json -RUN git clone --depth 1 --single-branch -b master https://github.com/jaedb/Iris.git /iris \ +ENV IRIS_VERSION=develop +RUN git clone --depth 1 --single-branch -b ${IRIS_VERSION} https://github.com/jaedb/Iris.git /iris \ && cd /iris \ && npm install \ && npm run prod \ @@ -115,13 +125,11 @@ RUN git clone --depth 1 --single-branch -b master https://github.com/jaedb/Iris. && mkdir -p /var/lib/mopidy/.config \ && ln -s /config /var/lib/mopidy/.config/mopidy \ # Allow mopidy user to run system commands (restart, local scan, etc) - && echo "mopidy ALL=NOPASSWD: /iris/mopidy_iris/system.sh" >> /etc/sudoers - -COPY VERSION / -COPY mopidy_iris/ /iris/mopidy_iris -COPY docker/mopidy/mopidy.example.conf /config/mopidy.conf -COPY docker/mopidy/pulse-client.conf /etc/pulse/client.conf -RUN echo "1" >> /IS_CONTAINER + && echo "mopidy ALL=NOPASSWD: /iris/mopidy_iris/system.sh" >> /etc/sudoers \ + # Enable container mode (disable restart option, etc.) + && echo "1" >> /IS_CONTAINER \ + # Copy Version file + && cp /iris/VERSION / # Install mopidy-spotify-gstspotify (Hack, not released yet!) # (https://github.com/kingosticks/mopidy-spotify/tree/gstspotifysrc-hack) @@ -131,8 +139,8 @@ RUN git clone --depth 1 -b gstspotifysrc-hack https://github.com/kingosticks/mop && cd .. \ && rm -rf mopidy-spotify -# Install additional Python dependencies -COPY docker/requirements.txt . +# Install additional mopidy extensions and Python dependencies via pip +COPY requirements.txt . RUN python3 -m pip install -r requirements.txt # Cleanup @@ -141,16 +149,23 @@ RUN apt-get clean all \ && rm -rf /root/.cache \ && rm -rf /iris/node_modules +# Start helper script. COPY docker/entrypoint.sh /entrypoint.sh +# Copy Default configuration for mopidy +COPY docker/mopidy/mopidy.example.conf /config/mopidy.conf + +# Copy the pulse-client configuratrion +COPY docker/mopidy/pulse-client.conf /etc/pulse/client.conf + # Allows any user to run mopidy, but runs by default as a randomly generated UID/GID. # RUN useradd -ms /bin/bash mopidy ENV HOME=/var/lib/mopidy RUN set -ex \ && usermod -G audio,sudo,pulse-access mopidy \ && mkdir /var/lib/mopidy/local \ - && chown mopidy:audio -R $HOME /entrypoint.sh \ - && chmod go+rwx -R $HOME /entrypoint.sh + && chown mopidy:audio -R $HOME /entrypoint.sh /iris \ + && chmod go+rwx -R $HOME /entrypoint.sh /iris # Runs as mopidy user by default. USER mopidy:audio From 6ca71d9c525fcabd577e9f56da92070ce43d7c14 Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Thu, 5 Jan 2023 21:35:37 +1300 Subject: [PATCH 18/20] Nested path to requirements.txt --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4ab21825..c883991f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -140,7 +140,7 @@ RUN git clone --depth 1 -b gstspotifysrc-hack https://github.com/kingosticks/mop && rm -rf mopidy-spotify # Install additional mopidy extensions and Python dependencies via pip -COPY requirements.txt . +COPY docker/requirements.txt . RUN python3 -m pip install -r requirements.txt # Cleanup From 4925d25442d814f72da7ccb5aec2d7e5134a6007 Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Sun, 15 Jan 2023 07:42:04 +1300 Subject: [PATCH 19/20] Removing advanced CodeCov workflow - Enabled basic version via GitHub directly --- .github/workflows/codeql-analysis.yml | 70 --------------------------- 1 file changed, 70 deletions(-) delete mode 100644 .github/workflows/codeql-analysis.yml diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 2a1da99f..00000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,70 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ master ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ master ] - schedule: - - cron: '29 5 * * 4' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'javascript', 'python' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://git.io/codeql-language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 From 58f487c2e26592c11671333773aa1528de88a589 Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Sun, 15 Jan 2023 07:42:36 +1300 Subject: [PATCH 20/20] Playlist Groups with name containing '/' - Escape to a space; may need expanding on if more characters start appearing --- src/js/components/GridItem.js | 2 +- src/js/views/Discover/Moods.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/js/components/GridItem.js b/src/js/components/GridItem.js index df18bb88..737f4543 100755 --- a/src/js/components/GridItem.js +++ b/src/js/components/GridItem.js @@ -122,7 +122,7 @@ const GridItem = ({ to = `/${item.type}/${encodeUri(item.uri)}`; if (item.name && item.type !== 'artist') { // Strip out "%"; this causes conflicts with our uri decoder - to += `/${encodeURIComponent(item.name.replace('%', ''))}`; + to += `/${encodeURIComponent(item.name.replace('%', '').replace('/', ''))}`; } } diff --git a/src/js/views/Discover/Moods.js b/src/js/views/Discover/Moods.js index 7803b1a7..405a6af3 100644 --- a/src/js/views/Discover/Moods.js +++ b/src/js/views/Discover/Moods.js @@ -140,7 +140,7 @@ class Mood extends React.Component { items={moods} details={['playlists']} right_column={['source']} - getLink={(item) => `/discover/moods/${encodeUri(item.uri)}/${item.name}`} + getLink={(item) => `/discover/moods/${encodeUri(item.uri)}/${encodeURIComponent(item.name.replace('%', '').replace('/', ''))}`} thumbnail />
@@ -150,7 +150,7 @@ class Mood extends React.Component {
`/discover/moods/${encodeUri(item.uri)}/${item.name}`} + getLink={(item) => `/discover/moods/${encodeUri(item.uri)}/${encodeURIComponent(item.name.replace('%', '').replace('/', ''))}`} tile />