-
Notifications
You must be signed in to change notification settings - Fork 198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add podcast support #875
Merged
Merged
Add podcast support #875
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
For now, the back-end is just able to return two hard-coded podcast channels when all the channels are requested. Everything else is "TODO".
The view can show the podcast channels and episoded provided by the back-end but cannot play them yet. The file podcastsviewcontroller.js still contains a lot of copy-pasted code from the albumsviewcontroller.js which should be refitted or removed.
The listheading widget was being rendered incorrectly in case the element had no details button enabled.
The podcast episode, channnel, and image are now properly shown in the player control bar, in the mediaSession integration, and in the desktop notification.
All these new classes and definitions are not yet used for anything.
The `occ` command `music:podcast-add` can now be used to add a single podcast channel from a RSS feed and the command `music:podcast-reset` can be used to reset all the previously added channels along with their episodes.
Get the data from the database tables instead of fetching it on the fly from a few hard-coded RSS feed URLs.
Implemented REST API endpoints to subscribe to a podcast channel, to unsubscribe it, to get an individual podcast channel and to reset all the subscribed channels.
It is at least theoretically possible that there would we identical podcast channels with differing RSS feed URLs. In such case, we should allow duplicate episode `guid`s to exist.
As part of this change, a new module podcstService was created to host the new functions. Also the handling of the creating/subscribing a new podcast channel was moved from navigationController to this new service.
To achieve this, a support had to be added to the listHeading directive to attach an actions menu. The menu contents are injected when instantiating the directive.
The new instance used to be always appended to the end of all instances although often this was not the correct place, according the order of the elements on the UI. Hence, the lazy loading didn't work correctly before reinitializing the view by navigating to another view and back.
On some podcast channels, the <lastBuildDate> tag changes very often, e.g. once every 15 minutes. This caused a lot of unnecessary updates on the database contents with such channels.
- The command now supports defining multiple RSS feed URLs at once - When adding a feed for multiple users, the feed is now fetched and parsed only once, and not separately for each user
This facilitates code reuse when adding the podcast support for the Subsonic and Ampache APIs: The class PodcastService contains API-agnostic logic while PodcastApiController is just a thin wrapper for it, providing the adaptation to the REST API provided for the web UI.
The entity classes PodcastChannel and PodcastEpisode now have functions called toSubsonicApi. These replace the former functions SubsonicController::podcastChannelToApi and SubsonicController::podcastChannelToApi. Similar design was previously applied to the Ampache API conversion of the podcast entity types. The target of this refactoring is to reduce the size of the monolithic SubsonicController. Similar refactoring should be eventually made to the other entity types, too, but that does not belong under this feature branch.
This same piece of logic, truncating a long HTML description and expanding it on click, was repeated three times in the various details templates. Now it is a reusable directive which opens the road to apply it also on the podcast descriptions (which is not done yet).
The full description may be viewed by clicking the truncated description.
The option may be give to force the updating of the episodes of all the targeted podcast channels, even when the podcast feed has not changed at all since the previous update. This may be desirable during the development when the parsing of the feed is changed by any means. It might be useful for the end-user, too, in case the database update somehow got unexpectedly aborted during the previous attempt.
- Extract also the season number from the podcast feed if available - The episode number is shown in the Podcasts view for each episode where available. If there is also a season number, the episode number is prefixed with it like "season-episode", e.g. "3-14.". - Sometimes also the title field in the RSS field contains the episode numbers. If the same number is present separately and as part of the title, then attempt to strip it off the title. - The season number was added to the episode details pane, too - The episode number was added to the Subsonic responses as property `track`. According to the Subsonic XML schema, the podcast episodes may contain all the same properties as the "normal" audio tracks. However, the tested clients (DSub and Ultrasonic) didn't seem to show the `track` property on episodes.
When subscribing to a podcast channel, add the available episodes to the DB in reverse order compared to the order of the RSS feed. Typically, the most recent episode is the first in the list, so this means adding the episodes from oldest to newest. Then, when new episodes are published, they will obviously be added after the first patch of the episodes, maintaining the same "oldest to newest" logic. Then, when returning the episodes through the REST API, the list is reversed once more to get the newest episodes first.
The play (or pause) icon was not shown in the episode list on the Podcasts view in front of the currently playing (or paused) episode.
…null" Many columns were accidentally marked as "not null" although they may quite well be missing in the RSS feed. This didn't break the application because the implementation details in the BusinessLayer were such that empty strings got stored instead of null values.
The`occ music:podcast-add` was actually totally broken because of a copy-paste error.
This is probably rarely useful but should be there for consistency of the UX with all the other views.
…cally When clicking the title or image of a podcast channel, the contained episodes are now enqueue to the play queue in chronological order. That is, they are played from bottom to top.
It's not quite clear if this method should return the episodes according to their original publish dates or by the order in which they have been added to the database. Now it's doing the latter which was a bit easier to achieve. The Subsonic API version has been bumbed to 1.13.0 to advertise the availability of this method; at least DSub uses only methods belonging to the claimed API version. The other new methods from v1.12.0 and 1.13.0 are `getTopSongs`, `getPlayQueue`, and `savePlayQueue`, which have been stubbed for now.
There's no technical reason, why there couldn't be collisions between track IDs and podcast episode IDs. This has to be taken into account when evaluating if a track should be visualized as the "current track" or not.
NC core provides suitable styling for this but OC core does not. Hence, we need to define the style on our own. The correct kind of styling already existed in style-navigation.css but that was applied only within the actions menu. These style definitions were now moved to their own file style-actions-menu.css, and they were made to apply both on the navigation pane and elsewhere within the Music app.
Previously, while there were no podcast channels, the actions menu item "Reload channels" only appeared disabled but it could actually be clicked. This triggered a toast with text "All channels were already up-to-date".
Shown while waiting for the contents for the pane.
When the details pane (for any content type) was closed and then opened again for any content type requiring closing, there was a flicker when the previous content was visible on the screen for a fraction of a second before being replaced by the loading spinner. This was visible at least when opening details pane for a podcast channel/episode, a track, or an album.
Also, when creating the first channel, there is now a loading spinner shown in the view. To facilitate all this, all methods of PodcastService were modified to return promises. This replaced signaling via $rootScope.$emit which was really designed only to be used when triggering operations from the navigation pane actions menu.
The same format is used also on the response of the Ampache action `handshake`. The example responses in the Ampache API documentation actually use the American format like "08/19/21 22:53 PM" but I hope that this is just an error in the spec and/or in Ampache SW since using ambiguous format like that in any API makes no sense.
This timestamp is part of the specified Ampache podcast responses so we need it after all. It is now also included in the channel details shown on the web UI. This field is still excluded when judging if the RSS feed has actually changed after the previous podcast update (because on some channels, the lastBuildDate changes very ofter without any other changes). This means that if only the lastBuildDate is updated in the feed, then the user will not see this even with manual update from the UI.
The `--force` flag now forces an update also on the data stored in the oc_music_podcast_channels table. Previously, the forcing was applied only on the episodes table.
Scrutinizer doesn't know that object of type SimpleXMLElement may be evaluated as false, hence claim that the argument could be actually null.
The support was almost there, but enabling it for this content type had been forgotten previously.
The inspection completed: 129 updated code elements |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR implements the support for podcasts as requested in #786.
This turned out to be one of the most extensive features ever implemented for the project within a single PR. This is largely because the feature has inter-connections with so many other features. Some of the implemented sub-features include:
getPodcasts
,getNewestPodcasts
,refreshPodcasts
,createPodcastChannel
,deletePodcastChannel
star
andunstar
createBookmark
andgetBookmarks
podcasts
,podcast
,podcast_create
,podcast_delete
,podcast_episodes
,podcast_episode
,update_podcast
get_indexes
,stats
,flag
,get_art
,download
,stream
occ
toolmusic:podcast-add
,music:podcast-reset
,music:podcast-update