Skip to content

Commit

Permalink
Merge pull request #3 from cinderblockgames/develop
Browse files Browse the repository at this point in the history
Tracking .playing
  • Loading branch information
cinderblockgames authored Jul 8, 2021
2 parents e06bff0 + 055f615 commit dcc2d76
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 62 deletions.
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ Pauses the current song.
Pauses the current song and resets the current time to zero.

### `cindrM.song.next()`
Plays the next song in the playlist, cycling back to the beginning of the playlist if the current song is the last song in the playlist.
Skips to the next song in the playlist, cycling back to the beginning of the playlist if the current song is the last song in the playlist.

### `cindrM.song.previous()`
Plays the previous song in the playlist, cycling back to the end of the playlist if the current song is the first song in the playlist.
In the first two seconds of the current song, skips to the previous song in the playlist, cycling back to the end of the playlist if the current song is the first song in the playlist. After the first two seconds of the current song, restarts the current song.

### `cindrM.song.seekPercent(percent)`
*Valid values: [`0`, `100`]*
Expand All @@ -120,7 +120,7 @@ Adds the provided song to the end of the playlist.
Inserts the provided song at the specified (zero-based) index, pushing back any songs at or above the specified index.

### `cindrM.playlist.remove(index)`
Removes the song at the specified (zero-based) index and returns it. If the removed song is the current song, the next song (if any) will start playing.
Removes the song at the specified (zero-based) index and returns it. If the removed song is the current song, skips to the next song (if any).

### `cindrM.playlist.clear()`
Removes all songs from the playlist.
Expand All @@ -132,7 +132,7 @@ Replaces the playlist with the provided set of songs.
Plays the first song in the playlist.

### `cindrM.playlist.seek(index)`
Plays the song at the specified (zero-based) index.
Skips to the song at the specified (zero-based) index.


## Player
Expand Down Expand Up @@ -177,7 +177,10 @@ The following options are available to customize the behavior of the UI manageme


### `cindrM.getInternals()`
Returns the internal tracking object used by cindr.musicPlayer.js. If you need direct access to the audio element, you can find it by calling `cindrM.getInternals().audio`.
Returns the internal tracking object used by cindr.musicPlayer.js. The following properties may be of interest:

- `cindrM.getInternals().audio` provides direct access to the audio element.
- `cindrM.getInternals().playing` indicates whether the player is currently playing.

**NOTE: Making changes to the internal tracking object is unsupported and can result in unpredictable behavior.**

Expand Down Expand Up @@ -255,7 +258,7 @@ A stop control will [stop](README.md#cindrmsongstop) the current song on click.
A next control will skip to the [next](README.md#cindrmsongnext) song on click.

### `previous`
A previous control will skip to the [previous](README.md#cindrmsongprevious) song on click.
In the first two seconds of the current song, a previous control will skip to the [previous](README.md#cindrmsongprevious) song on click. After the first two seconds of the current song, a previous control will restart the current song on click.

### `shuffle`
A shuffle control will [shuffle or unshuffle](README.md#cindrmplayershuffleshuffle) the playlist on click. It will also have the class `cindrM-shuffling` while shuffle is enabled.
Expand Down
127 changes: 71 additions & 56 deletions src/cindr.musicPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const cindrM = new EventTarget();

const player = {
audio: document.createElement('audio'),
playing: false,

volume: -1,
muted: false,
Expand All @@ -36,13 +37,13 @@ const cindrM = new EventTarget();
// Continue playing through the playlist.
player.audio.addEventListener('ended', () => {
if (player.repeat == 'song') {
cindr.song.play();
cindr.playlist.seek(playlist.index);
} else if (!player.shuffle && (player.index + 1) < player.playlist.length) {
cindr.song.next();
} else if (player.shuffle && (player.shuffled.indexOf(player.index) + 1) < player.shuffled.length) {
cindr.song.next();
} else if (player.repeat == 'playlist') {
cindr.playlist.play();
cindr.playlist.seek(0);
} else {
cindr.song.stop();
}
Expand Down Expand Up @@ -109,14 +110,22 @@ const cindrM = new EventTarget();
// Helpers.

play: function play(index) {
const play = player.playing;

player.index = player.shuffled[index];
player.audio.pause();
player.audio.currentTime = 0;
player.audio.src = player.playlist[player.index].url;
player.audio.play();

if (play) {
player.audio.play();
}

events.songchange();
events.play();

if (play) {
events.play();
}
}

};
Expand Down Expand Up @@ -207,7 +216,7 @@ const cindrM = new EventTarget();
node.classList.add('cindrM-repeating-song');
node.classList.remove('cindrM-repeating-playlist');
});
} else { // if (type == 'playlist')
} else if (type == 'playlist') {
nodes.forEach(node => {
node.classList.remove('cindrM-repeating-none');
node.classList.remove('cindrM-repeating-song');
Expand Down Expand Up @@ -298,7 +307,8 @@ const cindrM = new EventTarget();
if (clean) {
for (let index = node.attributes.length - 1; index >= 0; index--) {
const attr = node.attributes[index].nodeName;
if (attr.startsWith('data-')) {
if (['data-cindrM-song-info', 'data-cindrM-song-meta',
'data-cindrm-song-info', 'data-cindrm-song-meta'].includes(attr)) {
node.removeAttribute(attr);
}
}
Expand Down Expand Up @@ -455,52 +465,66 @@ const cindrM = new EventTarget();
cindr.song = {

play: function play() {
if (player.playlist.length >= 0) {
if (player.playlist.length == 0) {
output.warn('Playlist empty; ignoring call to song.play().');
} else if (player.playing) {
output.info('Already playing; ignoring call to song.play().');
} else {
if (player.index > -1) {
player.audio.play();
player.playing = true;
events.play();
} else {
cindr.playlist.play();
}
} else {
output.warn('Playlist empty; ignoring call to song.play().');
}
},

pause: function pause() {
if (player.playlist.length >= 0) {
if (player.playlist.length == 0) {
output.warn('Playlist empty; ignoring call to song.pause().');
} else if (!player.playing) {
output.info('Already paused; ignoring call to song.pause().');
} else {
player.audio.pause();
player.playing = false;
events.pause();
} else {
output.warn('Playlist empty; ignoring call to song.pause().');
}
},

stop: function stop() {
if (player.playlist.length >= 0) {
if (player.playlist.length == 0) {
output.warn('Playlist empty; ignoring call to song.stop().');
} else if (!player.playing) {
if (player.audio.currentTime == 0) {
output.info('Already stopped; ignoring call to song.stop().');
} else {
player.audio.currentTime = 0;
}
} else {
cindr.song.pause();
player.audio.currentTime = 0;
} else {
output.warn('Playlist empty; ignoring call to song.stop().');
}
},

next: function next() {
if (player.playlist.length > 0) {
if (player.playlist.length == 0) {
output.warn('Playlist empty; ignoring call to song.next().');
} else {
if (player.shuffle) {
shuffler.next();
} else if ((player.index + 1) < player.playlist.length) {
cindr.playlist.seek(player.index + 1);
} else {
cindr.playlist.play();
cindr.playlist.seek(0);
}
} else {
output.warn('Playlist empty; ignoring call to song.next().');
}
},

previous: function previous() {
if (player.playlist.length > 0) {
if (player.playlist.length == 0) {
output.warn('Playlist empty; ignoring call to song.previous().');
} else {
if (player.audio.currentTime > 2 && player.audio.duration > 2) {
// If we're over two seconds into the song, start it over.
player.audio.currentTime = 0;
Expand All @@ -511,10 +535,6 @@ const cindrM = new EventTarget();
} else {
cindr.playlist.seek(player.playlist.length - 1);
}
events.songchange();
}
else {
output.warn('Playlist empty; ignoring call to song.previous().');
}
},

Expand Down Expand Up @@ -584,18 +604,15 @@ const cindrM = new EventTarget();
removed = player.playlist.splice(index, 1);
player.index--;
} else if (index == player.index) {
player.audio.pause();
player.audio.currentTime = 0;
if ((player.index + 1) < player.playlist.length) {
removed = player.playlist.splice(index, 1);
cindr.playlist.seek(player.index);
} else if (player.index > 0) {
} else {
if (player.playing) {
cindr.song.stop();
}
removed = player.playlist.splice(index, 1);
player.index--;
} else { // if player.index == 0
removed = player.playlist;
player.index = -1;
player.playlist = [];
}
} else { // if (index > player.index)
removed = player.playlist.splice(index, 1);
Expand All @@ -616,8 +633,9 @@ const cindrM = new EventTarget();
},

replace: function replace(songs) {
player.audio.pause();
player.audio.currentTime = 0;
if (player.playing) {
player.song.stop();
}

if (songs.length > 0) {
player.index = 0;
Expand All @@ -636,6 +654,7 @@ const cindrM = new EventTarget();

play: function play() {
if (player.playlist.length > 0) {
player.playing = true; // Set to true before calling seek so that seek plays the song.
cindr.playlist.seek(0);
} else {
output.warn('Playlist empty; ignoring call to playlist.play().');
Expand All @@ -644,15 +663,23 @@ const cindrM = new EventTarget();

seek: function seek(index) {
if (strict.gte(index, 0) && strict.lt(index, player.playlist.length)) {
const play = player.playing;

player.index = index;
player.audio.pause();
player.audio.currentTime = 0;
player.audio.src = player.playlist[player.index].url;
player.audio.play();

if (play) {
player.audio.play();
}

shuffler.reset();
events.songchange();
events.play();

if (play) {
events.play();
}
} else {
output.warn('Ignoring invalid value sent to playlist.seek(index).', index);
}
Expand Down Expand Up @@ -752,43 +779,31 @@ const cindrM = new EventTarget();
if (document.querySelector('[data-cindrM-control]')) {
// play
document.querySelectorAll('[data-cindrM-control~="play"]').forEach(node =>
node.addEventListener('click', function click() {
if (!this.classList.contains('cindrM-playing')) {
cindr.song.play();
}
})
node.addEventListener('click', cindr.song.play)
);
cindr.addEventListener('play', update.playControl);

// pause
document.querySelectorAll('[data-cindrM-control~="pause"]').forEach(node =>
node.addEventListener('click', function click() {
if (!this.classList.contains('cindrM-paused')) {
cindr.song.pause();
}
})
node.addEventListener('click', cindr.song.pause)
);
cindr.addEventListener('pause', update.pauseControl);
update.pauseControl(); // Set UI.

// stop
document.querySelectorAll('[data-cindrM-control~="stop"]').forEach(node =>
node.addEventListener('click', function click() {
if (!this.classList.contains('cindrM-paused')) {
cindr.song.stop();
}
})
node.addEventListener('click', cindr.song.stop)
);

// next
document.querySelectorAll('[data-cindrM-control~="next"]').forEach(node => {
node.addEventListener('click', cindr.song.next);
});
document.querySelectorAll('[data-cindrM-control~="next"]').forEach(node =>
node.addEventListener('click', cindr.song.next)
);

// previous
document.querySelectorAll('[data-cindrM-control~="previous"]').forEach(node => {
node.addEventListener('click', cindr.song.previous);
});
document.querySelectorAll('[data-cindrM-control~="previous"]').forEach(node =>
node.addEventListener('click', cindr.song.previous)
);

// shuffle
document.querySelectorAll('[data-cindrM-control~="shuffle"]').forEach(node =>
Expand Down

0 comments on commit dcc2d76

Please sign in to comment.