diff --git a/components/Global/runtimeticks.tsx b/components/Global/runtimeticks.tsx index 23283914..847573d3 100644 --- a/components/Global/runtimeticks.tsx +++ b/components/Global/runtimeticks.tsx @@ -1,5 +1,6 @@ import { pad } from "lodash"; import { Text } from "./text"; +import { convertRunTimeTicksToSeconds } from "@/helpers/runtimeticks"; export default function RunTimeTicks({ children } : { children?: number | null | undefined }) : React.JSX.Element { if (!!!children) @@ -12,11 +13,8 @@ export default function RunTimeTicks({ children } : { children?: number | null | function calculateRunTimeFromTicks(runTimeTicks: number) : string { - // Convert ticks to seconds - // https://emby.media/community/index.php?/topic/63357-runtimeticks-microseconds-milliseconds-or-nanoseconds/ - const runTimeMilliseconds = runTimeTicks / 10000; - const runTimeTotalSeconds = Math.floor(runTimeMilliseconds / 1000); + const runTimeTotalSeconds = convertRunTimeTicksToSeconds(runTimeTicks); const runTimeHours = Math.floor(runTimeTotalSeconds / 3600); const runTimeMinutes = Math.floor((runTimeTotalSeconds % 3600) / 60) diff --git a/components/Global/slider.tsx b/components/Global/slider.tsx index 7a43785f..5c253027 100644 --- a/components/Global/slider.tsx +++ b/components/Global/slider.tsx @@ -22,7 +22,7 @@ export function HorizontalSlider({ return ( - + ) } diff --git a/components/Player/hooks/index.ts b/components/Player/hooks/index.ts index d1bcb28a..76c8af71 100644 --- a/components/Player/hooks/index.ts +++ b/components/Player/hooks/index.ts @@ -6,10 +6,10 @@ const CAPABILITIES: Capability[] = [ Capability.Pause, Capability.Play, Capability.PlayFromId, + Capability.SeekTo, Capability.Skip, Capability.SkipToNext, - Capability.SkipToPrevious, - Capability.SeekTo, + Capability.SkipToPrevious ] export const useSetupPlayer = () => useQuery({ @@ -21,7 +21,7 @@ export const useSetupPlayer = () => useQuery({ capabilities: CAPABILITIES, notificationCapabilities: CAPABILITIES, compactCapabilities: CAPABILITIES - }) - }) + }); + }); } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/helpers/mappings.ts b/helpers/mappings.ts index 830b6043..9e4fb44b 100644 --- a/helpers/mappings.ts +++ b/helpers/mappings.ts @@ -4,6 +4,7 @@ import { TrackType } from "react-native-track-player"; import { Api } from "@jellyfin/sdk"; import { QueuingType } from "../enums/queuing-type"; import querystring from "querystring" +import { getImageApi } from "@jellyfin/sdk/lib/utils/api"; const container = "opus,mp3,aac,m4a,flac,webma,webm,wav,ogg,mpa,wma"; @@ -33,9 +34,10 @@ export function mapDtoToTrack(api: Api, sessionId: string, item: BaseItemDto, qu album: item.Album, artist: item.Artists?.join(", "), duration: item.RunTimeTicks, + artwork: getImageApi(api).getItemImageUrlById(item.Id!), ItemId: item.Id!, - ArtistId: item.ParentId, + ArtistId: item.AlbumArtists![0].Id!, AlbumId: item.AlbumId!, QueuingType: queuingType ?? QueuingType.DirectlyQueued } as JellifyTrack diff --git a/helpers/runtimeticks.ts b/helpers/runtimeticks.ts new file mode 100644 index 00000000..d92ed784 --- /dev/null +++ b/helpers/runtimeticks.ts @@ -0,0 +1,16 @@ +export function convertSecondsToRunTimeTicks(seconds: number) { + + const runTimeMilliseconds = seconds * 1000 * 10000; + + return runTimeMilliseconds; +} + +export function convertRunTimeTicksToSeconds(ticks: number) { + // Convert ticks to seconds + // https://emby.media/community/index.php?/topic/63357-runtimeticks-microseconds-milliseconds-or-nanoseconds/ + const runTimeMilliseconds = ticks / 10000; + + const runTimeTotalSeconds = Math.floor(runTimeMilliseconds / 1000); + + return runTimeTotalSeconds; +} \ No newline at end of file diff --git a/player/handlers.ts b/player/handlers.ts index 8b311c93..bc5f2105 100644 --- a/player/handlers.ts +++ b/player/handlers.ts @@ -1,5 +1,7 @@ +import { Progress } from "react-native-track-player"; import { JellifyTrack } from "../types/JellifyTrack"; import { PlaystateApi } from "@jellyfin/sdk/lib/generated-client/api/playstate-api"; +import { convertSecondsToRunTimeTicks } from "@/helpers/runtimeticks"; export async function handlePlaybackStopped(sessionId: string, playstateApi: PlaystateApi, track: JellifyTrack) { console.debug("Stopping playback for session"); @@ -21,4 +23,16 @@ export async function handlePlaybackStarted(sessionId: string, playstateApi: Pla ItemId: track.ItemId } }) -} \ No newline at end of file +} + +export async function handlePlaybackProgressUpdated(sessionId: string, playstateApi: PlaystateApi, track: JellifyTrack, progress: Progress) { + console.debug("Reporting playback progress"); + + return playstateApi.reportPlaybackProgress({ + playbackProgressInfo: { + SessionId: sessionId, + ItemId: track.ItemId, + PositionTicks: convertSecondsToRunTimeTicks(progress.position) + } + }); +} diff --git a/player/provider.tsx b/player/provider.tsx index 0199f53b..dc807240 100644 --- a/player/provider.tsx +++ b/player/provider.tsx @@ -84,24 +84,24 @@ const PlayerContextInitializer = () => { const isPlayerReady = useSetupPlayer().isSuccess; useTrackPlayerEvents([ + Event.PlaybackProgressUpdated, Event.PlaybackActiveTrackChanged, ], async (event) => { switch (event.type) { + case (Event.PlaybackProgressUpdated) : { + if (event.position === event.duration - 10) { + handlePlaybackStopped(sessionId, playStateApi, nowPlaying!) + } + } + case (Event.PlaybackActiveTrackChanged) : { console.debug("Active track changed"); - // Scrobble previously played track - if (nowPlaying) { - handlePlaybackStopped(sessionId, playStateApi, nowPlaying) - } - - console.debug("Setting nowPlaying") - // Sleep to prevent flickering in players when skipping to a queue index sleep(250).then(async () => { setNowPlaying(await TrackPlayer.getActiveTrack() as JellifyTrack | undefined); - }) + }); } } }) diff --git a/player/service.ts b/player/service.ts index 1184786f..a08cc9dc 100644 --- a/player/service.ts +++ b/player/service.ts @@ -18,6 +18,7 @@ export async function PlaybackService() { TrackPlayer.addEventListener(Event.RemoteSkip, () => { TrackPlayer.skipToNext(); }); + TrackPlayer.addEventListener(Event.RemotePrevious, () => { TrackPlayer.skipToPrevious(); });