@@ -263,11 +263,11 @@ export class Player {
263263 EndReasons . LOAD_FAILED
264264 ] . includes ( state . reason )
265265 ) {
266- if ( this . isUpdatingTrack && state . reason === 'finished' ) {
266+ if ( ( this . isUpdatingTrack || this . _isSeeking ) && state . reason === 'finished' ) {
267267 logger (
268268 'debug' ,
269269 'Player' ,
270- `Ignoring spurious idle/finished event during track replacement for guild ${ this . guildId } .`
270+ `Ignoring spurious idle/finished event during track replacement/seek for guild ${ this . guildId } .`
271271 )
272272 return
273273 }
@@ -456,7 +456,7 @@ export class Player {
456456 async _fetchResource ( info , urlData , startTime ) {
457457 await getStreamProcessor ( )
458458
459- if ( startTime )
459+ if ( startTime !== undefined )
460460 urlData . additionalData = { startTime, ...urlData . additionalData }
461461
462462 const track = urlData ?. newTrack ? urlData ?. newTrack ?. info : info
@@ -806,7 +806,7 @@ export class Player {
806806 this . _isSeeking = true
807807 try {
808808 const sourceName = this . track . info . sourceName
809- const unsupportedSources = [ 'deezer' , ' local']
809+ const unsupportedSources = [ 'local' ]
810810
811811 let seekPromise
812812 if ( ! this . streamInfo ?. url ) {
@@ -844,11 +844,20 @@ export class Player {
844844 )
845845 }
846846 }
847- if ( ! unsupportedSources . includes ( sourceName ) && this . streamInfo ?. url ) {
847+
848+ const source = this . nodelink . sources . getSource ( sourceName )
849+ const canNativeSeek = sourceName === 'deezer' || ( source && typeof source . loadStream === 'function' )
850+
851+ if ( ! unsupportedSources . includes ( sourceName ) && this . streamInfo ?. url && sourceName !== 'deezer' ) {
848852 seekPromise = this . _seekeableSeek (
849853 seekPosition ,
850854 endTime !== undefined ? endTime : this . track . endTime
851855 )
856+ } else if ( canNativeSeek ) {
857+ seekPromise = this . _seekUsingSource (
858+ seekPosition ,
859+ endTime !== undefined ? endTime : this . track . endTime
860+ )
852861 } else {
853862 seekPromise = this . _legacySeek (
854863 seekPosition ,
@@ -867,6 +876,91 @@ export class Player {
867876 }
868877 }
869878
879+ async _seekUsingSource ( position , endTime ) {
880+ if ( ! this . track ) return false
881+
882+ logger (
883+ 'debug' ,
884+ 'Player' ,
885+ `Seeking using source (native) to ${ position } ms for guild ${ this . guildId } `
886+ )
887+
888+ this . position = position
889+ this . track . endTime = endTime
890+
891+ const trackInfo = {
892+ ...this . track . info ,
893+ audioTrackId : this . track . audioTrackId
894+ }
895+
896+ const urlData = await this . nodelink . sources . getTrackUrl ( trackInfo )
897+ this . streamInfo = { ...urlData , trackInfo : this . track . info }
898+
899+ if ( urlData . exception ) {
900+ const err = new Error ( urlData . exception . message )
901+ this . _onError ( err )
902+ return false
903+ }
904+
905+ if ( ! this . connection ) {
906+ this . _initConnection ( )
907+ }
908+
909+ if (
910+ ! this . connection ||
911+ ! this . connection . udpInfo ||
912+ ! this . connection . udpInfo . secretKey
913+ ) {
914+ await this . waitEvent (
915+ 'stateChange' ,
916+ ( s ) => s . status === 'connected' && this . connection ?. udpInfo ?. secretKey
917+ )
918+ }
919+
920+ if (
921+ ! this . connection ||
922+ ! this . connection . udpInfo ||
923+ ! this . connection . udpInfo . secretKey
924+ ) {
925+ const errorMessage = `Voice connection for guild ${ this . guildId } is not ready (missing UDP info). Aborting playback.`
926+ logger ( 'error' , 'Player' , errorMessage )
927+ this . _onError ( new Error ( errorMessage ) )
928+ return false
929+ }
930+
931+ const fetched = await this . _fetchResource (
932+ this . track . info ,
933+ urlData ,
934+ position
935+ )
936+ if ( fetched . exception ) {
937+ const err = new Error ( fetched . exception . message )
938+ this . _onError ( err )
939+ return false
940+ }
941+
942+ if ( this . connection . audioStream ) {
943+ this . connection . audioStream ?. destroy ( )
944+ }
945+
946+ const resource = fetched . stream
947+ if ( this . volumePercent !== 100 ) {
948+ resource . setVolume ( this . volumePercent / 100 )
949+ }
950+
951+ this . setFilters ( this . filters )
952+
953+ logger (
954+ 'debug' ,
955+ 'Player' ,
956+ `Playing resource for guild ${ this . guildId } after source seek`
957+ )
958+ this . connection . play ( resource )
959+ await this . waitEvent ( 'playerStateChange' , ( s ) => s . status === 'playing' )
960+
961+ return true
962+ }
963+
870964 async _seekeableSeek ( position , endTime ) {
871965 await getStreamProcessor ( )
872966
0 commit comments