Skip to content

Commit

Permalink
Add support for the Invidious YouTube add-on (#979)
Browse files Browse the repository at this point in the history
* Add setting for the preferred YouTube add-on (#978)

* Move creation of YouTube plugin URL to a dedicated method (#978)

This makes it easier to extend the functionality and
incorporate other add-ons for YouTube.

* Create a dedicated method for the default YouTube add-on (#978)

* Add support for the Invidious add-on for YouTube (#978)
  • Loading branch information
wtimme authored Nov 20, 2023
1 parent 0724097 commit 5e6f971
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 23 deletions.
3 changes: 3 additions & 0 deletions app/src/main/java/org/xbmc/kore/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ public static String getRemoteBarItemsPrefKey(int hostId) {
public static final String KEY_PREF_ALWAYS_SENDTOKODI_ADDON = "pref_always_sendtokodi_addon";
public static final boolean DEFAULT_PREF_ALWAYS_SENDTOKODI_ADDON = false;

public static final String KEY_PREF_YOUTUBE_ADDON_ID = "pref_youtube_addon_id";
public static final String DEFAULT_PREF_YOUTUBE_ADDON_ID = "plugin.video.youtube";

public static final String KEY_PREF_NAV_DRAWER_ITEMS = "pref_nav_drawer_items";
public static String getNavDrawerItemsPrefKey(int hostId) {
return Settings.KEY_PREF_NAV_DRAWER_ITEMS + hostId;
Expand Down
119 changes: 96 additions & 23 deletions app/src/main/java/org/xbmc/kore/ShareOpenActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import android.webkit.MimeTypeMap;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.preference.PreferenceManager;

Expand Down Expand Up @@ -247,29 +248,8 @@ private String toPluginUrl(Uri playuri) {
.getBoolean(Settings.KEY_PREF_ALWAYS_SENDTOKODI_ADDON,
Settings.DEFAULT_PREF_ALWAYS_SENDTOKODI_ADDON);
if (!alwaysSendToKodi) {
if (host.endsWith("youtube.com")) {
String videoId = playuri.getQueryParameter("v");
String playlistId = playuri.getQueryParameter("list");
Uri.Builder pluginUri = new Uri.Builder()
.scheme("plugin")
.authority("plugin.video.youtube")
.path("play/");
boolean valid = false;
if (videoId != null) {
valid = true;
pluginUri.appendQueryParameter("video_id", videoId);
}
if (playlistId != null) {
valid = true;
pluginUri.appendQueryParameter("playlist_id", playlistId)
.appendQueryParameter("order", "default");
}
if (valid) {
return pluginUri.build().toString();
}
} else if (host.endsWith("youtu.be")) {
return "plugin://plugin.video.youtube/play/?video_id="
+ playuri.getLastPathSegment();
if (host.endsWith("youtube.com") || host.endsWith("youtu.be")) {
return toYouTubePluginUrl(playuri);
} else if (host.endsWith("vimeo.com")) {
return PluginUrlUtils.toPluginUrlVimeo(playuri);
} else if (host.endsWith("svtplay.se")) {
Expand Down Expand Up @@ -317,6 +297,99 @@ private String toPluginUrl(Uri playuri) {
return null;
}

/**
* Converts a YouTube url to a Kodi plugin URL.
*
* @param playuri some URL for YouTube
* @return plugin URL
*/
@Nullable
private String toYouTubePluginUrl(Uri playuri) {
String preferredYouTubeAddonId = PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
.getString(Settings.KEY_PREF_YOUTUBE_ADDON_ID, Settings.DEFAULT_PREF_YOUTUBE_ADDON_ID);

if (preferredYouTubeAddonId.equals("plugin.video.invidious")) {
return toInvidiousYouTubePluginUrl(playuri);
} else {
return toDefaultYouTubePluginUrl(playuri);
}
}

/**
* Converts a YouTube url to an URL for the default YouTube add-on (plugin.video.youtube)
*
* @param playuri some URL for YouTube
* @return plugin URL
*/
@Nullable
private String toDefaultYouTubePluginUrl(Uri playuri) {
String host = playuri.getHost();

if (host.endsWith("youtube.com")) {
String videoId = playuri.getQueryParameter("v");
String playlistId = playuri.getQueryParameter("list");
Uri.Builder pluginUri = new Uri.Builder()
.scheme("plugin")
.authority("plugin.video.youtube")
.path("play/");
boolean valid = false;
if (videoId != null) {
valid = true;
pluginUri.appendQueryParameter("video_id", videoId);
}
if (playlistId != null) {
valid = true;
pluginUri.appendQueryParameter("playlist_id", playlistId)
.appendQueryParameter("order", "default");
}
if (valid) {
return pluginUri.build().toString();
}
} else if (host.endsWith("youtu.be")) {
return "plugin://plugin.video.youtube/play/?video_id="
+ playuri.getLastPathSegment();
}

return null;
}

/**
* Converts a YouTube url to an URL for the Invidious YouTube add-on (plugin.video.invidious)
*
* @param playuri some URL for YouTube
* @return plugin URL
*/
@Nullable
private String toInvidiousYouTubePluginUrl(Uri playuri) {
String host = playuri.getHost();

Uri.Builder pluginUri = new Uri.Builder()
.scheme("plugin")
.authority("plugin.video.invidious")
.path("/")
.appendQueryParameter("action", "play_video");

String videoIdParameterKey = "video_id";

String videoId;
if (host.endsWith("youtube.com")) {
videoId = playuri.getQueryParameter("v");
} else if (host.endsWith("youtu.be")) {
videoId = playuri.getLastPathSegment();
} else {
return null;
}

if (videoId == null) {
return null;
}

return pluginUri
.appendQueryParameter(videoIdParameterKey, videoId)
.build()
.toString();
}

boolean isMediaFile(String mimeType) {
if (mimeType == null) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@ private void setupPreferences() {
useHWVolKeysPref.setSummary(useHWVolKeysPref.getEntry());
}

// Preferred YouTube addon
ListPreference preferredYouTubeAddonPref = findPreference(Settings.KEY_PREF_YOUTUBE_ADDON_ID);
if (preferredYouTubeAddonPref != null) {
preferredYouTubeAddonPref.setSummary(preferredYouTubeAddonPref.getEntry());
}

// About preference
String nameAndVersion = context.getString(R.string.app_name);
try {
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,14 @@
<item>when_in_foreground</item>
</string-array>

<!-- Constants for the Preferred Youtube addon setting in preferences -->
<string-array name="preferred_youtube_addon_keys_array">
<item>@string/preferred_youtube_addon_youtube</item>
<item>@string/preferred_youtube_addon_invidious</item>
</string-array>
<string-array translatable="false" name="preferred_youtube_addon_values_array">
<item>plugin.video.youtube</item>
<item>plugin.video.invidious</item>
</string-array>

</resources>
5 changes: 5 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -492,4 +492,9 @@
<string name="use_hardware_volume_keys_always">Always</string>
<string name="use_hardware_volume_keys_when_in_foreground">When Kore is in the foreground</string>

<!-- Strings for the Preferred YouTube addon setting -->
<string name="preferred_youtube_addon">Preferred YouTube addon</string>
<string name="preferred_youtube_addon_youtube">YouTube (plugin.video.youtube)</string>
<string name="preferred_youtube_addon_invidious">Invidious (plugin.video.invidious)</string>

</resources>
8 changes: 8 additions & 0 deletions app/src/main/res/xml/preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@
android:defaultValue="false"
app:singleLineTitle="false"/>

<ListPreference
android:key="pref_youtube_addon_id"
android:title="@string/preferred_youtube_addon"
android:entries="@array/preferred_youtube_addon_keys_array"
android:entryValues="@array/preferred_youtube_addon_values_array"
android:defaultValue="plugin.video.youtube"
app:singleLineTitle="false"/>

</PreferenceCategory>

<PreferenceCategory android:title="@string/theme">
Expand Down

0 comments on commit 5e6f971

Please sign in to comment.