diff --git a/chromecast/src/api.ts b/chromecast/src/api.ts
index 04afde59..5aca81ea 100644
--- a/chromecast/src/api.ts
+++ b/chromecast/src/api.ts
@@ -81,6 +81,14 @@ export type Item = {
direct: string;
transmux: string;
};
+ nextEpisode: {
+ id: number,
+ slug: string,
+ },
+ previousEpisode: {
+ id: number,
+ slug: string,
+ }
};
export const getItem = async (slug: string, apiUrl: string) => {
@@ -125,3 +133,13 @@ export const itemToMovie = (item: Item) => {
return metadata;
}
+export const itemToMedia = (item: Item, apiUrl: string) => {
+ const media = new cast.framework.messages.MediaInformation();
+ media.contentUrl = item.link.direct;
+ media.metadata = item.isMovie
+ ? itemToMovie(item)
+ : itemToTvMetadata(item);
+ media.customData = item;
+ media.customData.serverUrl = apiUrl;
+ return media;
+}
diff --git a/chromecast/src/index.ts b/chromecast/src/index.ts
index 5a3ff202..52532960 100644
--- a/chromecast/src/index.ts
+++ b/chromecast/src/index.ts
@@ -18,7 +18,8 @@
* along with Kyoo. If not, see .
*/
-import { getItem, itemToMovie, itemToTvMetadata } from "./api";
+import { getItem, itemToMedia } from "./api";
+import { Queue } from "./queue";
const Command = cast.framework.messages.Command;
const context = cast.framework.CastReceiverContext.getInstance();
@@ -35,27 +36,22 @@ playerManager.setSupportedMediaCommands(
Command.STREAM_TRANSFER,
);
-
-
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
async (loadRequestData) => {
if (loadRequestData.media.contentUrl && loadRequestData.media.metadata) return loadRequestData;
+ const apiUrl = loadRequestData.media.customData.serverUrl;
const item = await getItem(
loadRequestData.media.contentId,
- loadRequestData.media.customData.serverUrl,
+ apiUrl,
);
if (!item) {
return new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType.LOAD_FAILED);
}
- loadRequestData.media.contentUrl = item.link.direct;
- loadRequestData.media.metadata = item.isMovie
- ? itemToMovie(item)
- : itemToTvMetadata(item);
- loadRequestData.media.customData = item;
+ loadRequestData.media = itemToMedia(item, apiUrl);
return loadRequestData;
},
);
-context.start();
+context.start({ queue: new Queue() });
diff --git a/chromecast/src/queue.ts b/chromecast/src/queue.ts
new file mode 100644
index 00000000..927a97b9
--- /dev/null
+++ b/chromecast/src/queue.ts
@@ -0,0 +1,73 @@
+/*
+ * Kyoo - A portable and vast media library solution.
+ * Copyright (c) Kyoo.
+ *
+ * See AUTHORS.md and LICENSE file in the project root for full license information.
+ *
+ * Kyoo is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * Kyoo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Kyoo. If not, see .
+ */
+
+import { QueueManager } from "chromecast-caf-receiver/cast.framework";
+import { LoadRequestData, QueueData, QueueItem } from "chromecast-caf-receiver/cast.framework.messages";
+import { getItem, Item, itemToMedia } from "./api";
+
+export class Queue extends cast.framework.QueueBase {
+ queue: QueueManager | null;
+
+ constructor() {
+ super();
+ this.queue = cast.framework.CastReceiverContext.getInstance().getPlayerManager().getQueueManager();
+ }
+
+ initialize(requestData: LoadRequestData): QueueData {
+ if (requestData.queueData) return requestData.queueData;
+
+ const queueData = new cast.framework.messages.QueueData();
+ queueData.name = "queue";
+ queueData.items = [requestData.media];
+ return queueData;
+ }
+
+ async nextItems(itemId?: number): Promise {
+ const current = this.queue?.getItems().find(x => x.itemId == itemId);
+ if (!current || !current.media?.contentId || !current.media.customData?.serverUrl) return [];
+
+ const metadata = current?.media?.customData as Item;
+ const apiUrl = current.media?.customData.serverUrl;
+ if (!metadata.nextEpisode) return [];
+
+ const item = await getItem(metadata.nextEpisode.slug, apiUrl);
+ if (!item) return [];
+
+ const data = new cast.framework.messages.QueueItem();
+ data.media = itemToMedia(item, apiUrl);
+ return [data];
+ }
+
+ async prevItems(itemId?: number): Promise {
+ const current = this.queue?.getItems().find(x => x.itemId == itemId);
+ if (!current || !current.media?.contentId || !current.media.customData?.serverUrl) return [];
+
+ const metadata = current?.media?.customData as Item;
+ const apiUrl = current.media?.customData.serverUrl;
+ if (!metadata.previousEpisode) return [];
+
+ const item = await getItem(metadata.previousEpisode.slug, apiUrl);
+ if (!item) return [];
+
+ const data = new cast.framework.messages.QueueItem();
+ data.media = itemToMedia(item, apiUrl);
+ return [data];
+ }
+}
diff --git a/front/src/player/cast/state.tsx b/front/src/player/cast/state.tsx
index cb7e9e5c..1fc1c3ba 100644
--- a/front/src/player/cast/state.tsx
+++ b/front/src/player/cast/state.tsx
@@ -91,7 +91,7 @@ export const useCastController = () => {
[cast.framework.RemotePlayerEventType.DURATION_CHANGED, (event) => setDuration(event.value)],
[
cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED,
- () => setMedia(player.mediaInfo?.customData),
+ () => setMedia(player.mediaInfo?.customData ?? null),
],
];