mirror of
https://github.com/janishutz/MusicPlayerV2.git
synced 2025-11-25 13:04:23 +00:00
more progress on apple music integration
This commit is contained in:
@@ -18,17 +18,19 @@ createApp( {
|
|||||||
computed: {
|
computed: {
|
||||||
songQueue() {
|
songQueue() {
|
||||||
let ret = [];
|
let ret = [];
|
||||||
|
let pos = 0;
|
||||||
for ( let song in this.songs ) {
|
for ( let song in this.songs ) {
|
||||||
if ( parseInt( song ) >= this.queuePos ) {
|
if ( pos >= this.queuePos ) {
|
||||||
ret.push( this.songs[ song ] );
|
ret.push( this.songs[ song ] );
|
||||||
}
|
}
|
||||||
|
pos += 1;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
getTimeUntil() {
|
getTimeUntil() {
|
||||||
return ( song ) => {
|
return ( song ) => {
|
||||||
let timeRemaining = 0;
|
let timeRemaining = 0;
|
||||||
for ( let i = this.queuePos; i < this.songs.length; i++ ) {
|
for ( let i = this.queuePos; i < Object.keys( this.songs ).length; i++ ) {
|
||||||
if ( this.songs[ i ] == song ) {
|
if ( this.songs[ i ] == song ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<span class="material-symbols-outlined loading-spinner">autorenew</span>
|
<span class="material-symbols-outlined loading-spinner">autorenew</span>
|
||||||
<h3>Loading playlists...</h3>
|
<h3>Loading playlists...</h3>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="playlist in playlists" class="song-list" @click="selectPlaylist( playlist.id )">
|
<div v-for="playlist in playlists" class="song-list" @click="selectPlaylist( playlist.id )" style="cursor: pointer;">
|
||||||
<h3>{{ playlist.title }}</h3>
|
<h3>{{ playlist.title }}</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -62,10 +62,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="song-info">
|
<div class="song-info">
|
||||||
<div class="song-info-wrapper">
|
<div class="song-info-wrapper">
|
||||||
<div v-if="hasSelectedPlaylist" style="cursor: pointer;">
|
<img v-if="hasSelectedPlaylist" :src="playingSong.coverArtURL" class="image">
|
||||||
<span class="material-symbols-outlined image" v-if="!playingSong.hasCoverArt">music_note</span>
|
|
||||||
<img v-else :src="playingSong.coverArtURL" class="image">
|
|
||||||
</div>
|
|
||||||
<span class="material-symbols-outlined image" v-else>music_note</span>
|
<span class="material-symbols-outlined image" v-else>music_note</span>
|
||||||
<div class="name">
|
<div class="name">
|
||||||
<h3>{{ playingSong.title ?? 'No song selected' }}</h3>
|
<h3>{{ playingSong.title ?? 'No song selected' }}</h3>
|
||||||
@@ -79,8 +76,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="slider">
|
<div class="slider">
|
||||||
<progress id="progress-slider" class="progress-slider" :value="sliderProgress" max="1000" @mousedown="( e ) => { setPos( e ) }"
|
<progress id="progress-slider" class="progress-slider" :value="sliderProgress" max="1000" @mousedown="( e ) => { setPos( e ) }"
|
||||||
:class="active ? '' : 'slider-inactive'"></progress>
|
:class="hasSelectedPlaylist ? '' : 'slider-inactive'"></progress>
|
||||||
<div v-if="active" id="slider-knob" @mousedown="( e ) => { startMove( e ) }"
|
<div v-if="hasSelectedPlaylist" id="slider-knob" @mousedown="( e ) => { startMove( e ) }"
|
||||||
:style="'left: ' + ( parseInt( originalPos ) + parseInt( sliderPos ) ) + 'px;'">
|
:style="'left: ' + ( parseInt( originalPos ) + parseInt( sliderPos ) ) + 'px;'">
|
||||||
<div id="slider-knob-style"></div>
|
<div id="slider-knob-style"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -95,9 +92,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="pool-wrapper">
|
<div class="pool-wrapper">
|
||||||
<div style="width: 100%;" class="song-list-wrapper">
|
<div style="width: 100%;" class="song-list-wrapper">
|
||||||
<div v-for="song in songQueue" class="song-list" :class="[ isPlaying ? ( playingSong.filename === song.filename ? 'playing': 'not-playing' ) : 'not-playing', !isPlaying && playingSong.filename === song.filename ? 'active-song': undefined ]">
|
<div v-for="song in songQueue" class="song-list" :class="[ isPlaying ? ( playingSong.queuePos == song.queuePos ? 'playing': 'not-playing' ) : 'not-playing', !isPlaying && playingSong.filename === song.filename ? 'active-song': undefined ]">
|
||||||
<img :src="song.coverArtURL" class="song-image">
|
<img :src="song.coverArtURL" class="song-image">
|
||||||
<div v-if="playingSong.filename === song.filename && isPlaying" class="playing-symbols">
|
<div v-if="playingSong.queuePos == song.queuePos && isPlaying" class="playing-symbols">
|
||||||
<div class="playing-symbols-wrapper">
|
<div class="playing-symbols-wrapper">
|
||||||
<div class="playing-bar" id="bar-1"></div>
|
<div class="playing-bar" id="bar-1"></div>
|
||||||
<div class="playing-bar" id="bar-2"></div>
|
<div class="playing-bar" id="bar-2"></div>
|
||||||
@@ -105,7 +102,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="material-symbols-outlined play-icon" @click="play( song )">play_arrow</span>
|
<span class="material-symbols-outlined play-icon" @click="play( song )">play_arrow</span>
|
||||||
<span class="material-symbols-outlined pause-icon" @click="pause( song )">pause</span>
|
<span class="material-symbols-outlined pause-icon" @click="control( 'pause' )">pause</span>
|
||||||
<h3>{{ song.title }}</h3>
|
<h3>{{ song.title }}</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ const app = Vue.createApp( {
|
|||||||
sliderPos: 0,
|
sliderPos: 0,
|
||||||
originalPos: 0,
|
originalPos: 0,
|
||||||
sliderProgress: 0,
|
sliderProgress: 0,
|
||||||
position: 0,
|
|
||||||
active: false,
|
active: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -43,7 +42,6 @@ const app = Vue.createApp( {
|
|||||||
} else {
|
} else {
|
||||||
this.musicKit.authorize().then( () => {
|
this.musicKit.authorize().then( () => {
|
||||||
this.isLoggedIn = true;
|
this.isLoggedIn = true;
|
||||||
this.musicKit.play();
|
|
||||||
this.initMusicKit();
|
this.initMusicKit();
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
@@ -58,7 +56,8 @@ const app = Vue.createApp( {
|
|||||||
app: {
|
app: {
|
||||||
name: 'MusicPlayer',
|
name: 'MusicPlayer',
|
||||||
build: '2'
|
build: '2'
|
||||||
}
|
},
|
||||||
|
storefrontId: 'CH',
|
||||||
} );
|
} );
|
||||||
this.config.devToken = token;
|
this.config.devToken = token;
|
||||||
this.musicKit = MusicKit.getInstance();
|
this.musicKit = MusicKit.getInstance();
|
||||||
@@ -66,9 +65,18 @@ const app = Vue.createApp( {
|
|||||||
this.isLoggedIn = true;
|
this.isLoggedIn = true;
|
||||||
this.config.userToken = this.musicKit.musicUserToken;
|
this.config.userToken = this.musicKit.musicUserToken;
|
||||||
}
|
}
|
||||||
|
this.musicKit.addEventListener( 'playbackStateDidChange', ( e ) => {
|
||||||
|
console.log( 'Playback state changed: ', e );
|
||||||
|
} );
|
||||||
|
this.musicKit.addEventListener( 'queueItemsDidChange', ( event ) => {
|
||||||
|
console.log( 'Queue items changed:', event );
|
||||||
|
} );
|
||||||
|
this.musicKit.addEventListener( 'playbackError', ( event ) => {
|
||||||
|
console.log( 'Playback Error:', event );
|
||||||
|
} );
|
||||||
this.musicKit.addEventListener( 'mediaItemDidChange', ( e ) => {
|
this.musicKit.addEventListener( 'mediaItemDidChange', ( e ) => {
|
||||||
// Assemble this.playingSong
|
// Assemble this.playingSong
|
||||||
// Also add additional items to queue if there are new
|
// TODO: Also add additional items to queue if there are new
|
||||||
// items that weren't previously shown (limitation of MusicKitJS).
|
// items that weren't previously shown (limitation of MusicKitJS).
|
||||||
this.playingSong = {
|
this.playingSong = {
|
||||||
'artist': e.item.attributes.artistName,
|
'artist': e.item.attributes.artistName,
|
||||||
@@ -78,13 +86,19 @@ const app = Vue.createApp( {
|
|||||||
// 'bpm': metadata[ 'common' ][ 'bpm' ],
|
// 'bpm': metadata[ 'common' ][ 'bpm' ],
|
||||||
'genre': e.item.attributes.genreNames,
|
'genre': e.item.attributes.genreNames,
|
||||||
'duration': Math.round( e.item.attributes.durationInMillis / 1000 ),
|
'duration': Math.round( e.item.attributes.durationInMillis / 1000 ),
|
||||||
'filename': e.item.id,
|
'filename': this.songQueue[ this.musicKit.player.nowPlayingItemIndex ].filename,
|
||||||
'coverArtOrigin': 'api',
|
'coverArtOrigin': 'api',
|
||||||
|
'hasCoverArt': true,
|
||||||
|
'queuePos': this.musicKit.player.nowPlayingItemIndex,
|
||||||
}
|
}
|
||||||
let url = e.item.attributes.artwork.url;
|
let url = e.item.attributes.artwork.url;
|
||||||
url = url.replace( '{w}', e.item.attributes.artwork.width );
|
url = url.replace( '{w}', e.item.attributes.artwork.width );
|
||||||
url = url.replace( '{h}', e.item.attributes.artwork.height );
|
url = url.replace( '{h}', e.item.attributes.artwork.height );
|
||||||
this.songQueue[ item ][ 'coverArtURL' ] = url;
|
this.playingSong[ 'coverArtURL' ] = url;
|
||||||
|
this.queuePos = this.musicKit.player.nowPlayingItemIndex;
|
||||||
|
this.sendUpdate( 'playingSong' );
|
||||||
|
this.sendUpdate( 'pos' );
|
||||||
|
this.sendUpdate( 'queuePos' );
|
||||||
} );
|
} );
|
||||||
this.apiGetRequest( 'https://api.music.apple.com/v1/me/library/playlists', this.playlistHandler );
|
this.apiGetRequest( 'https://api.music.apple.com/v1/me/library/playlists', this.playlistHandler );
|
||||||
} );
|
} );
|
||||||
@@ -130,30 +144,28 @@ const app = Vue.createApp( {
|
|||||||
},
|
},
|
||||||
selectPlaylist( id ) {
|
selectPlaylist( id ) {
|
||||||
this.isPreparingToPlay = true;
|
this.isPreparingToPlay = true;
|
||||||
this.musicKit.api.library.playlist( id ).then( playlist => {
|
this.musicKit.setQueue( { playlist: id } ).then( () => {
|
||||||
const tracks = playlist.relationships.tracks.data.map( tracks => tracks.id );
|
|
||||||
|
|
||||||
this.musicKit.setQueue( { songs: tracks } ).then( () => {
|
|
||||||
try {
|
try {
|
||||||
this.musicKit.play();
|
this.control( 'play' );
|
||||||
const songQueue = this.musicKit.player.queue.items;
|
const songQueue = this.musicKit.player.queue.items;
|
||||||
for ( let item in songQueue ) {
|
for ( let item in songQueue ) {
|
||||||
this.songQueue[ item ] = {
|
this.songQueue[ item ] = {
|
||||||
'artist': songQueue[ item ].attributes.artistName,
|
'artist': songQueue[ item ].attributes.artistName,
|
||||||
'title': songQueue[ item ].attributes.name,
|
'title': songQueue[ item ].attributes.name,
|
||||||
'year': songQueue[ item ].attributes.releaseDate,
|
'year': songQueue[ item ].attributes.releaseDate,
|
||||||
// Think about bpm analysis
|
|
||||||
// 'bpm': metadata[ 'common' ][ 'bpm' ],
|
|
||||||
'genre': songQueue[ item ].attributes.genreNames,
|
'genre': songQueue[ item ].attributes.genreNames,
|
||||||
'duration': Math.round( songQueue[ item ].attributes.durationInMillis / 1000 ),
|
'duration': Math.round( songQueue[ item ].attributes.durationInMillis / 1000 ),
|
||||||
'filename': songQueue[ item ].id,
|
'filename': songQueue[ item ].id,
|
||||||
'coverArtOrigin': 'api',
|
'coverArtOrigin': 'api',
|
||||||
|
'hasCoverArt': true,
|
||||||
|
'queuePos': item,
|
||||||
}
|
}
|
||||||
let url = songQueue[ item ].attributes.artwork.url;
|
let url = songQueue[ item ].attributes.artwork.url;
|
||||||
url = url.replace( '{w}', songQueue[ item ].attributes.artwork.width );
|
url = url.replace( '{w}', songQueue[ item ].attributes.artwork.width );
|
||||||
url = url.replace( '{h}', songQueue[ item ].attributes.artwork.height );
|
url = url.replace( '{h}', songQueue[ item ].attributes.artwork.height );
|
||||||
this.songQueue[ item ][ 'coverArtURL' ] = url;
|
this.songQueue[ item ][ 'coverArtURL' ] = url;
|
||||||
}
|
}
|
||||||
|
this.sendUpdate( 'songQueue' );
|
||||||
// TODO: Load additional data from file
|
// TODO: Load additional data from file
|
||||||
this.hasSelectedPlaylist = true;
|
this.hasSelectedPlaylist = true;
|
||||||
this.isPreparingToPlay = false;
|
this.isPreparingToPlay = false;
|
||||||
@@ -164,12 +176,11 @@ const app = Vue.createApp( {
|
|||||||
}
|
}
|
||||||
} ).catch( err => {
|
} ).catch( err => {
|
||||||
console.error( 'ERROR whilst settings Queue', err );
|
console.error( 'ERROR whilst settings Queue', err );
|
||||||
} )
|
|
||||||
} );
|
} );
|
||||||
},
|
},
|
||||||
handleDrag( e ) {
|
handleDrag( e ) {
|
||||||
if ( this.isDragging ) {
|
if ( this.isDragging ) {
|
||||||
if ( 0 < this.originalPos + e.screenX - this.offset && this.originalPos + e.screenX - this.offset < document.getElementById( 'progress-slider-' + this.name ).clientWidth - 5 ) {
|
if ( 0 < this.originalPos + e.screenX - this.offset && this.originalPos + e.screenX - this.offset < document.getElementById( 'progress-slider' ).clientWidth - 5 ) {
|
||||||
this.sliderPos = e.screenX - this.offset;
|
this.sliderPos = e.screenX - this.offset;
|
||||||
this.calcProgressPos();
|
this.calcProgressPos();
|
||||||
}
|
}
|
||||||
@@ -189,17 +200,18 @@ const app = Vue.createApp( {
|
|||||||
this.calcPlaybackPos();
|
this.calcPlaybackPos();
|
||||||
},
|
},
|
||||||
setPos ( e ) {
|
setPos ( e ) {
|
||||||
if ( this.active ) {
|
if ( this.hasSelectedPlaylist ) {
|
||||||
this.originalPos = e.offsetX;
|
this.originalPos = e.offsetX;
|
||||||
this.calcProgressPos();
|
this.calcProgressPos();
|
||||||
this.calcPlaybackPos();
|
this.calcPlaybackPos();
|
||||||
|
this.musicKit.seekToTime( this.pos );
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
calcProgressPos() {
|
calcProgressPos() {
|
||||||
this.sliderProgress = Math.ceil( ( this.originalPos + parseInt( this.sliderPos ) ) / ( document.getElementById( 'progress-slider-' + this.name ).clientWidth - 5 ) * 1000 );
|
this.sliderProgress = Math.ceil( ( this.originalPos + parseInt( this.sliderPos ) ) / ( document.getElementById( 'progress-slider' ).clientWidth - 5 ) * 1000 );
|
||||||
},
|
},
|
||||||
calcPlaybackPos() {
|
calcPlaybackPos() {
|
||||||
this.pos = Math.round( ( this.originalPos + parseInt( this.sliderPos ) ) / ( document.getElementById( 'progress-slider-' + this.name ).clientWidth - 5 ) * this.duration );
|
this.pos = Math.round( ( this.originalPos + parseInt( this.sliderPos ) ) / ( document.getElementById( 'progress-slider' ).clientWidth - 5 ) * this.playingSong.duration );
|
||||||
},
|
},
|
||||||
sendUpdate( update ) {
|
sendUpdate( update ) {
|
||||||
let data = {};
|
let data = {};
|
||||||
@@ -212,6 +224,7 @@ const app = Vue.createApp( {
|
|||||||
} else if ( update === 'songQueue' ) {
|
} else if ( update === 'songQueue' ) {
|
||||||
data = this.songQueue;
|
data = this.songQueue;
|
||||||
} else if ( update === 'queuePos' ) {
|
} else if ( update === 'queuePos' ) {
|
||||||
|
this.queuePos = this.musicKit.player.nowPlayingItemIndex >= 0 ? this.musicKit.player.nowPlayingItemIndex : 0;
|
||||||
data = this.queuePos;
|
data = this.queuePos;
|
||||||
}
|
}
|
||||||
let fetchOptions = {
|
let fetchOptions = {
|
||||||
@@ -228,9 +241,16 @@ const app = Vue.createApp( {
|
|||||||
},
|
},
|
||||||
control( action ) {
|
control( action ) {
|
||||||
if ( action === 'play' ) {
|
if ( action === 'play' ) {
|
||||||
this.musicKit.play();
|
this.isPlaying = true;
|
||||||
|
this.musicKit.player.play().catch( err => {
|
||||||
|
console.log( 'player failed to start' );
|
||||||
|
console.log( err );
|
||||||
|
} );
|
||||||
|
try {
|
||||||
|
clearInterval( this.progressTracker );
|
||||||
|
} catch( err ) {};
|
||||||
this.progressTracker = setInterval( () => {
|
this.progressTracker = setInterval( () => {
|
||||||
this.pos = this.musicKit.currentPlaybackTime;
|
this.pos = parseInt( this.musicKit.player.currentPlaybackTime );
|
||||||
|
|
||||||
const minuteCount = Math.floor( this.pos / 60 );
|
const minuteCount = Math.floor( this.pos / 60 );
|
||||||
this.playbackPosBeautified = minuteCount + ':';
|
this.playbackPosBeautified = minuteCount + ':';
|
||||||
@@ -270,13 +290,13 @@ const app = Vue.createApp( {
|
|||||||
this.isPlaying = false;
|
this.isPlaying = false;
|
||||||
this.sendUpdate( 'isPlaying' );
|
this.sendUpdate( 'isPlaying' );
|
||||||
} else if ( action === 'replay10' ) {
|
} else if ( action === 'replay10' ) {
|
||||||
this.musicKit.seekToTime( this.musicKit.currentPlaybackTime > 10 ? musicPlayer.currentPlaybackTime - 10 : 0 );
|
this.musicKit.seekToTime( this.musicKit.player.currentPlaybackTime > 10 ? musicPlayer.player.currentPlaybackTime - 10 : 0 );
|
||||||
this.pos = musicPlayer.currentTime;
|
this.pos = this.musicKit.player.currentPlaybackTime;
|
||||||
this.sendUpdate( 'pos' );
|
this.sendUpdate( 'pos' );
|
||||||
} else if ( action === 'forward10' ) {
|
} else if ( action === 'forward10' ) {
|
||||||
if ( this.musicKit.currentPlaybackTime < ( this.playingSong.duration - 10 ) ) {
|
if ( this.musicKit.player.currentPlaybackTime < ( this.playingSong.duration - 10 ) ) {
|
||||||
this.musicKit.seekToTime( this.musicKit.currentTime + 10 );
|
this.musicKit.seekToTime( this.musicKit.player.currentPlaybackTime + 10 );
|
||||||
this.pos = this.musicKit.currentPlaybackTime;
|
this.pos = this.musicKit.player.currentPlaybackTime;
|
||||||
this.sendUpdate( 'pos' );
|
this.sendUpdate( 'pos' );
|
||||||
// Get currently playing song and get duration from there
|
// Get currently playing song and get duration from there
|
||||||
} else {
|
} else {
|
||||||
@@ -294,40 +314,54 @@ const app = Vue.createApp( {
|
|||||||
this.musicKit.seekToTime( 0 );
|
this.musicKit.seekToTime( 0 );
|
||||||
this.sendUpdate( 'pos' );
|
this.sendUpdate( 'pos' );
|
||||||
} else if ( action === 'next' ) {
|
} else if ( action === 'next' ) {
|
||||||
this.$emit( 'update', { 'type': 'next' } );
|
this.sendUpdate( 'queuePos' );
|
||||||
|
this.musicKit.skipToNextItem();
|
||||||
|
this.control( 'play' );
|
||||||
} else if ( action === 'previous' ) {
|
} else if ( action === 'previous' ) {
|
||||||
if ( this.pos > 3 ) {
|
if ( this.pos > 3 ) {
|
||||||
this.pos = 0;
|
this.pos = 0;
|
||||||
musicPlayer.currentTime = 0;
|
this.musicKit.seekToTime( 0 );
|
||||||
this.sendUpdate( 'pos' );
|
this.sendUpdate( 'pos' );
|
||||||
|
this.sendUpdate( 'queuePos' );
|
||||||
|
this.control( 'play' );
|
||||||
} else {
|
} else {
|
||||||
this.$emit( 'update', { 'type': 'previous' } );
|
this.musicKit.skipToPreviousItem();
|
||||||
|
this.control( 'play' );
|
||||||
}
|
}
|
||||||
} else if ( action === 'shuffleOff' ) {
|
} else if ( action === 'shuffleOff' ) {
|
||||||
this.$emit( 'update', { 'type': 'shuffleOff' } );
|
|
||||||
this.isShuffleEnabled = false;
|
this.isShuffleEnabled = false;
|
||||||
|
this.musicKit.PlayerShuffleMode = 'off';
|
||||||
} else if ( action === 'shuffleOn' ) {
|
} else if ( action === 'shuffleOn' ) {
|
||||||
this.$emit( 'update', { 'type': 'shuffle' } );
|
this.musicKit.PlayerShuffleMode = 'songs';
|
||||||
this.isShuffleEnabled = true;
|
this.isShuffleEnabled = true;
|
||||||
} else if ( action === 'repeatOne' ) {
|
} else if ( action === 'repeatOne' ) {
|
||||||
this.repeatMode = 'one';
|
this.repeatMode = 'one';
|
||||||
|
this.musicKit.PlayerRepeatMode = 'one';
|
||||||
} else if ( action === 'repeatAll' ) {
|
} else if ( action === 'repeatAll' ) {
|
||||||
this.$emit( 'update', { 'type': 'repeat' } );
|
this.musicKit.PlayerRepeatMode = 'all';
|
||||||
this.repeatMode = 'all';
|
this.repeatMode = 'all';
|
||||||
} else if ( action === 'repeatOff' ) {
|
} else if ( action === 'repeatOff' ) {
|
||||||
this.$emit( 'update', { 'type': 'repeatOff' } );
|
this.musicKit.PlayerRepeatMode = 'none';
|
||||||
this.repeatMode = 'off';
|
this.repeatMode = 'off';
|
||||||
} else if ( action === 'exitFancyView' ) {
|
}
|
||||||
this.isShowingFancyView = false;
|
},
|
||||||
this.$emit( 'update', { 'type': 'fancyView', 'status': false } );
|
play( song ) {
|
||||||
|
let foundSong = 0;
|
||||||
|
for ( let s in this.songQueue ) {
|
||||||
|
if ( this.songQueue[ s ] === song ) {
|
||||||
|
foundSong = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.control( 'stop' );
|
||||||
|
this.musicKit.player.changeToMediaAtIndex( foundSong );
|
||||||
|
this.control( 'play' );
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
pos() {
|
pos() {
|
||||||
if ( !this.isDragging ) {
|
if ( !this.isDragging ) {
|
||||||
this.sliderProgress = Math.ceil( this.position / this.duration * 1000 + 2 );
|
this.sliderProgress = Math.ceil( this.pos / this.playingSong.duration * 1000 + 2 );
|
||||||
this.originalPos = Math.ceil( this.position / this.duration * ( document.getElementById( 'progress-slider-' + this.name ).scrollWidth - 5 ) );
|
this.originalPos = Math.ceil( this.pos / this.playingSong.duration * ( document.getElementById( 'progress-slider' ).scrollWidth - 5 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,17 +22,19 @@ createApp( {
|
|||||||
computed: {
|
computed: {
|
||||||
songQueue() {
|
songQueue() {
|
||||||
let ret = [];
|
let ret = [];
|
||||||
|
let pos = 0;
|
||||||
for ( let song in this.songs ) {
|
for ( let song in this.songs ) {
|
||||||
if ( parseInt( song ) >= this.queuePos ) {
|
if ( pos >= this.queuePos ) {
|
||||||
ret.push( this.songs[ song ] );
|
ret.push( this.songs[ song ] );
|
||||||
}
|
}
|
||||||
|
pos += 1;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
getTimeUntil() {
|
getTimeUntil() {
|
||||||
return ( song ) => {
|
return ( song ) => {
|
||||||
let timeRemaining = 0;
|
let timeRemaining = 0;
|
||||||
for ( let i = this.queuePos; i < this.songs.length; i++ ) {
|
for ( let i = this.queuePos; i < Object.keys( this.songs ).length - 1; i++ ) {
|
||||||
if ( this.songs[ i ] == song ) {
|
if ( this.songs[ i ] == song ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -267,7 +269,7 @@ createApp( {
|
|||||||
},
|
},
|
||||||
animateBeat () {
|
animateBeat () {
|
||||||
$( '.beat-manual' ).stop();
|
$( '.beat-manual' ).stop();
|
||||||
const duration = Math.ceil( 60 / this.playingSong.bpm * 500 ) - 50;
|
const duration = Math.ceil( 60 / ( this.playingSong.bpm ?? 180 ) * 500 ) - 50;
|
||||||
$( '.beat-manual' ).fadeIn( 50 );
|
$( '.beat-manual' ).fadeIn( 50 );
|
||||||
setTimeout( () => {
|
setTimeout( () => {
|
||||||
$( '.beat-manual' ).fadeOut( duration );
|
$( '.beat-manual' ).fadeOut( duration );
|
||||||
|
|||||||
Reference in New Issue
Block a user