mirror of
https://github.com/janishutz/MusicPlayerV2.git
synced 2025-11-25 13:04:23 +00:00
apple-music integration working but unstable
This commit is contained in:
@@ -54,6 +54,9 @@ createApp( {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
startTimeTracker () {
|
startTimeTracker () {
|
||||||
|
try {
|
||||||
|
clearInterval( this.timeTracker );
|
||||||
|
} catch ( err ) {}
|
||||||
this.timeTracker = setInterval( () => {
|
this.timeTracker = setInterval( () => {
|
||||||
this.pos = ( new Date().getTime() - this.playingSong.startTime ) / 1000 + this.oldPos;
|
this.pos = ( new Date().getTime() - this.playingSong.startTime ) / 1000 + this.oldPos;
|
||||||
this.progressBar = ( this.pos / this.playingSong.duration ) * 1000;
|
this.progressBar = ( this.pos / this.playingSong.duration ) * 1000;
|
||||||
|
|||||||
1
frontend/.gitignore
vendored
1
frontend/.gitignore
vendored
@@ -24,3 +24,4 @@ pnpm-debug.log*
|
|||||||
|
|
||||||
#Electron-builder output
|
#Electron-builder output
|
||||||
/dist_electron
|
/dist_electron
|
||||||
|
test
|
||||||
@@ -58,49 +58,45 @@ const app = Vue.createApp( {
|
|||||||
build: '2'
|
build: '2'
|
||||||
},
|
},
|
||||||
storefrontId: 'CH',
|
storefrontId: 'CH',
|
||||||
} );
|
} ).then( () => {
|
||||||
this.config.devToken = token;
|
this.config.devToken = token;
|
||||||
this.musicKit = MusicKit.getInstance();
|
this.musicKit = MusicKit.getInstance();
|
||||||
if ( this.musicKit.isAuthorized ) {
|
if ( this.musicKit.isAuthorized ) {
|
||||||
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 ) => {
|
|
||||||
// Assemble this.playingSong
|
|
||||||
// TODO: Also add additional items to queue if there are new
|
|
||||||
// items that weren't previously shown (limitation of MusicKitJS).
|
|
||||||
this.playingSong = {
|
|
||||||
'artist': e.item.attributes.artistName,
|
|
||||||
'title': e.item.attributes.name,
|
|
||||||
'year': e.item.attributes.releaseDate,
|
|
||||||
// Think about bpm analysis
|
|
||||||
// 'bpm': metadata[ 'common' ][ 'bpm' ],
|
|
||||||
'genre': e.item.attributes.genreNames,
|
|
||||||
'duration': Math.round( e.item.attributes.durationInMillis / 1000 ),
|
|
||||||
'filename': this.songQueue[ this.musicKit.player.nowPlayingItemIndex ].filename,
|
|
||||||
'coverArtOrigin': 'api',
|
|
||||||
'hasCoverArt': true,
|
|
||||||
'queuePos': this.musicKit.player.nowPlayingItemIndex,
|
|
||||||
}
|
}
|
||||||
let url = e.item.attributes.artwork.url;
|
this.musicKit.shuffleMode = MusicKit.PlayerShuffleMode.off;
|
||||||
url = url.replace( '{w}', e.item.attributes.artwork.width );
|
this.musicKit.addEventListener( 'nowPlayingItemDidChange', ( e ) => {
|
||||||
url = url.replace( '{h}', e.item.attributes.artwork.height );
|
this.control( 'play' );
|
||||||
this.playingSong[ 'coverArtURL' ] = url;
|
// Assemble this.playingSong
|
||||||
this.queuePos = this.musicKit.player.nowPlayingItemIndex;
|
// TODO: Also add additional items to queue if there are new
|
||||||
this.sendUpdate( 'playingSong' );
|
// items that weren't previously shown (limitation of MusicKitJS).
|
||||||
this.sendUpdate( 'pos' );
|
if ( e.item ) {
|
||||||
this.sendUpdate( 'queuePos' );
|
this.playingSong = {
|
||||||
|
'artist': e.item.attributes.artistName,
|
||||||
|
'title': e.item.attributes.name,
|
||||||
|
'year': e.item.attributes.releaseDate,
|
||||||
|
// Think about bpm analysis
|
||||||
|
// 'bpm': metadata[ 'common' ][ 'bpm' ],
|
||||||
|
'genre': e.item.attributes.genreNames,
|
||||||
|
'duration': Math.round( e.item.attributes.durationInMillis / 1000 ),
|
||||||
|
'filename': this.songQueue[ this.musicKit.nowPlayingItemIndex ].filename,
|
||||||
|
'coverArtOrigin': 'api',
|
||||||
|
'hasCoverArt': true,
|
||||||
|
'queuePos': this.musicKit.nowPlayingItemIndex,
|
||||||
|
}
|
||||||
|
let url = e.item.attributes.artwork.url;
|
||||||
|
url = url.replace( '{w}', e.item.attributes.artwork.width );
|
||||||
|
url = url.replace( '{h}', e.item.attributes.artwork.height );
|
||||||
|
this.playingSong[ 'coverArtURL' ] = url;
|
||||||
|
this.queuePos = this.musicKit.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 );
|
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
@@ -147,14 +143,14 @@ const app = Vue.createApp( {
|
|||||||
this.musicKit.setQueue( { playlist: id } ).then( () => {
|
this.musicKit.setQueue( { playlist: id } ).then( () => {
|
||||||
try {
|
try {
|
||||||
this.control( 'play' );
|
this.control( 'play' );
|
||||||
const songQueue = this.musicKit.player.queue.items;
|
const songQueue = this.musicKit.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,
|
||||||
'genre': songQueue[ item ].attributes.genreNames,
|
'genre': songQueue[ item ].attributes.genreNames,
|
||||||
'duration': Math.round( songQueue[ item ].attributes.durationInMillis / 1000 ),
|
'duration': Math.round( songQueue[ item ].durationInMillis / 1000 ),
|
||||||
'filename': songQueue[ item ].id,
|
'filename': songQueue[ item ].id,
|
||||||
'coverArtOrigin': 'api',
|
'coverArtOrigin': 'api',
|
||||||
'hasCoverArt': true,
|
'hasCoverArt': true,
|
||||||
@@ -205,6 +201,7 @@ const app = Vue.createApp( {
|
|||||||
this.calcProgressPos();
|
this.calcProgressPos();
|
||||||
this.calcPlaybackPos();
|
this.calcPlaybackPos();
|
||||||
this.musicKit.seekToTime( this.pos );
|
this.musicKit.seekToTime( this.pos );
|
||||||
|
this.sendUpdate( 'pos' );
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
calcProgressPos() {
|
calcProgressPos() {
|
||||||
@@ -224,7 +221,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;
|
this.queuePos = this.musicKit.nowPlayingItemIndex >= 0 ? this.musicKit.nowPlayingItemIndex : 0;
|
||||||
data = this.queuePos;
|
data = this.queuePos;
|
||||||
}
|
}
|
||||||
let fetchOptions = {
|
let fetchOptions = {
|
||||||
@@ -239,18 +236,30 @@ const app = Vue.createApp( {
|
|||||||
console.error( err );
|
console.error( err );
|
||||||
} );
|
} );
|
||||||
},
|
},
|
||||||
|
// TODO: Reload queue if shuffle enabled
|
||||||
control( action ) {
|
control( action ) {
|
||||||
if ( action === 'play' ) {
|
if ( action === 'play' ) {
|
||||||
|
if( !this.musicKit || !this.isPlaying ) {
|
||||||
|
this.musicKit.play().then( () => {
|
||||||
|
this.sendUpdate( 'pos' );
|
||||||
|
} ).catch( err => {
|
||||||
|
console.log( 'player failed to start' );
|
||||||
|
console.log( err );
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
this.musicKit.pause().then( () => {
|
||||||
|
this.musicKit.play().catch( err => {
|
||||||
|
console.log( 'player failed to start' );
|
||||||
|
console.log( err );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
}
|
||||||
this.isPlaying = true;
|
this.isPlaying = true;
|
||||||
this.musicKit.player.play().catch( err => {
|
|
||||||
console.log( 'player failed to start' );
|
|
||||||
console.log( err );
|
|
||||||
} );
|
|
||||||
try {
|
try {
|
||||||
clearInterval( this.progressTracker );
|
clearInterval( this.progressTracker );
|
||||||
} catch( err ) {};
|
} catch( err ) {};
|
||||||
this.progressTracker = setInterval( () => {
|
this.progressTracker = setInterval( () => {
|
||||||
this.pos = parseInt( this.musicKit.player.currentPlaybackTime );
|
this.pos = parseInt( this.musicKit.currentPlaybackTime );
|
||||||
|
|
||||||
const minuteCount = Math.floor( this.pos / 60 );
|
const minuteCount = Math.floor( this.pos / 60 );
|
||||||
this.playbackPosBeautified = minuteCount + ':';
|
this.playbackPosBeautified = minuteCount + ':';
|
||||||
@@ -277,7 +286,7 @@ const app = Vue.createApp( {
|
|||||||
this.durationBeautified += secondCounts;
|
this.durationBeautified += secondCounts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 20 );
|
}, 200 );
|
||||||
this.sendUpdate( 'pos' );
|
this.sendUpdate( 'pos' );
|
||||||
this.sendUpdate( 'isPlaying' );
|
this.sendUpdate( 'isPlaying' );
|
||||||
} else if ( action === 'pause' ) {
|
} else if ( action === 'pause' ) {
|
||||||
@@ -290,13 +299,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.player.currentPlaybackTime > 10 ? musicPlayer.player.currentPlaybackTime - 10 : 0 );
|
this.musicKit.seekToTime( this.musicKit.currentPlaybackTime > 10 ? musicPlayer.player.currentPlaybackTime - 10 : 0 );
|
||||||
this.pos = this.musicKit.player.currentPlaybackTime;
|
this.pos = this.musicKit.currentPlaybackTime;
|
||||||
this.sendUpdate( 'pos' );
|
this.sendUpdate( 'pos' );
|
||||||
} else if ( action === 'forward10' ) {
|
} else if ( action === 'forward10' ) {
|
||||||
if ( this.musicKit.player.currentPlaybackTime < ( this.playingSong.duration - 10 ) ) {
|
if ( this.musicKit.currentPlaybackTime < ( this.playingSong.duration - 10 ) ) {
|
||||||
this.musicKit.seekToTime( this.musicKit.player.currentPlaybackTime + 10 );
|
this.musicKit.seekToTime( this.musicKit.currentPlaybackTime + 10 );
|
||||||
this.pos = this.musicKit.player.currentPlaybackTime;
|
this.pos = this.musicKit.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 {
|
||||||
@@ -314,47 +323,53 @@ 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.sendUpdate( 'queuePos' );
|
this.musicKit.skipToNextItem().then( () => {
|
||||||
this.musicKit.skipToNextItem();
|
this.sendUpdate( 'queuePos' );
|
||||||
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;
|
||||||
this.musicKit.seekToTime( 0 );
|
this.musicKit.seekToTime( 0 ).then( () => {
|
||||||
this.sendUpdate( 'pos' );
|
this.sendUpdate( 'pos' );
|
||||||
this.sendUpdate( 'queuePos' );
|
this.sendUpdate( 'queuePos' );
|
||||||
this.control( 'play' );
|
this.control( 'play' );
|
||||||
|
} );
|
||||||
} else {
|
} else {
|
||||||
this.musicKit.skipToPreviousItem();
|
this.musicKit.skipToPreviousItem().then( () => {
|
||||||
this.control( 'play' );
|
this.sendUpdate( 'queuePos' );
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
} else if ( action === 'shuffleOff' ) {
|
} else if ( action === 'shuffleOff' ) {
|
||||||
this.isShuffleEnabled = false;
|
this.isShuffleEnabled = false;
|
||||||
this.musicKit.PlayerShuffleMode = 'off';
|
this.musicKit.shuffleMode = MusicKit.PlayerShuffleMode.off;
|
||||||
} else if ( action === 'shuffleOn' ) {
|
} else if ( action === 'shuffleOn' ) {
|
||||||
this.musicKit.PlayerShuffleMode = 'songs';
|
this.musicKit.shuffleMode = 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';
|
this.musicKit.repeatMode = MusicKit.PlayerRepeatMode.one;
|
||||||
} else if ( action === 'repeatAll' ) {
|
} else if ( action === 'repeatAll' ) {
|
||||||
this.musicKit.PlayerRepeatMode = 'all';
|
this.musicKit.repeatMode = MusicKit.PlayerRepeatMode.all;
|
||||||
this.repeatMode = 'all';
|
this.repeatMode = 'all';
|
||||||
} else if ( action === 'repeatOff' ) {
|
} else if ( action === 'repeatOff' ) {
|
||||||
this.musicKit.PlayerRepeatMode = 'none';
|
this.musicKit.repeatMode = MusicKit.PlayerRepeatMode.none;
|
||||||
this.repeatMode = 'off';
|
this.repeatMode = 'off';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
play( song ) {
|
play( song ) {
|
||||||
|
// TODO: Look into this... seems to cancel the playlist and then autoplay similar music
|
||||||
|
// TODO: Also look at stability of player
|
||||||
let foundSong = 0;
|
let foundSong = 0;
|
||||||
for ( let s in this.songQueue ) {
|
for ( let s in this.songQueue ) {
|
||||||
if ( this.songQueue[ s ] === song ) {
|
if ( this.songQueue[ s ] === song ) {
|
||||||
foundSong = s;
|
foundSong = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.control( 'stop' );
|
this.musicKit.play().then( () => {
|
||||||
this.musicKit.player.changeToMediaAtIndex( foundSong );
|
this.musicKit.changeToMediaAtIndex( foundSong ).catch( ( err ) => {
|
||||||
this.control( 'play' );
|
console.log( err );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user