Backend playback tracking for lastfm plugin

Update slider to be smaller
This commit is contained in:
Violet Caulfield
2025-01-06 21:07:31 -06:00
parent 2cbd7db5ee
commit d5d6a67d80
8 changed files with 52 additions and 21 deletions

View File

@@ -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)

View File

@@ -22,7 +22,7 @@ export function HorizontalSlider({
return (
<TamaguiSlider
size="$3"
size="$4"
width={width}
value={value ? [value] : []}
max={max}
@@ -34,7 +34,7 @@ export function HorizontalSlider({
<TamaguiSlider.Track>
<TamaguiSlider.TrackActive />
</TamaguiSlider.Track>
<TamaguiSlider.Thumb circular index={0} />
<TamaguiSlider.Thumb circular index={0} size={"$3"} />
</TamaguiSlider>
)
}

View File

@@ -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
})
})
});
});
}
})
});

View File

@@ -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

16
helpers/runtimeticks.ts Normal file
View File

@@ -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;
}

View File

@@ -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
}
})
}
}
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)
}
});
}

View File

@@ -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);
})
});
}
}
})

View File

@@ -18,6 +18,7 @@ export async function PlaybackService() {
TrackPlayer.addEventListener(Event.RemoteSkip, () => {
TrackPlayer.skipToNext();
});
TrackPlayer.addEventListener(Event.RemotePrevious, () => {
TrackPlayer.skipToPrevious();
});