ts-audio icon indicating copy to clipboard operation
ts-audio copied to clipboard

AudioPlaylist cannot automatically play next song

Open mikhael28 opened this issue 2 years ago • 7 comments

Hi there! Love this library, you have done a fantastic job. I am making a simple audio player, and wrote up the following code below - however, the playlist does not automatically move onto the next song in the list after the current one finishes. I've tried setting loop to true, enabling shuffle, and playlist.end doesn't seem to work.

Here is the code below, is there something I'm missing? Using 0.7.0, latest release.

import { useState, useMemo, useEffect, useRef } from "react";
import {
  IoMdPlay,
  IoMdPause,
  IoMdSkipForward,
  IoMdSkipBackward,
  IoMdMusicalNote,
  IoMdMusicalNotes,
} from "react-icons/io";
import { AudioPlaylist } from "ts-audio";
import FatsNY from "../assets/mp3/FatsNY.mp3";
import PictureBall from "../assets/mp3/PictureBall.mp3";
import Silvery from "../assets/mp3/Silvery.mp3";
import SecretGarden from "../assets/mp3/SecretGarden.mp3";

export default function MusicPlayer(props: any) {
  const [currentSong, setCurrentSong] = useState(0);
  const [isPlaying, setIsPlaying] = useState(false);

  interface Song {
    title: string;
    artist: string;
    img_src: any;
    src: string;
  }

  const songs: Song[] = useMemo(
    () => [
      {
        title: "At the Moving Picture Ball",
        artist: "Maurice Burkhart",
        img_src: IoMdMusicalNote,
        src: PictureBall,
      },
      {
        title: "New York Yacht Club",
        artist: "Fats Waller",
        img_src: IoMdMusicalNote,
        src: FatsNY,
      },
      {
        title: "By the Lights of the Silvery",
        artist: "Fats Waller",
        img_src: IoMdMusicalNotes,
        src: Silvery,
      },
      {
        title: "Secret Garden",
        artist: "Unknown",
        img_src: IoMdMusicalNote,
        src: SecretGarden,
      },
    ],
    []
  );

  const playlist = useMemo(() => {
    return AudioPlaylist({
      files: songs.map((song: Song) => song.src),
      loop: false,
    });
  }, [songs]);

  playlist.on("start", (param) => {
    // doesn't seem to have any data in the param
    console.log(param);
  });

  playlist.on("end", (param) => {
    // doesn't seem to work
  });

  const handlePlay = () => {
    playlist.play();
    setIsPlaying(true);
  };

  const handlePause = () => {
    playlist.pause();
    setIsPlaying(false);
  };

  const handleSkip = () => {
    playlist.pause();
    playlist.next();
    setIsPlaying(true);

    setCurrentSong(
      (currentSong) => (currentSong + 1 + songs.length) % songs.length
    );
  };

  const handlePrevious = () => {
    playlist.pause();
    playlist.prev();
    setIsPlaying(true);
    setCurrentSong(
      (currentSong) => (currentSong - 1 + songs.length) % songs.length
    );
  };

  return (
    <div
      style={{
        backgroundColor: "gray",
        display: "flex",
        justifyContent: "space-between",
        paddingLeft: 20,
        paddingTop: 8,
      }}
    >
      <div>
        <h3>Now Playing</h3>
        <p>
          {songs[currentSong].title} by {songs[currentSong].artist}
        </p>
      </div>

      <div>
        <IoMdSkipBackward
          style={{ cursor: "pointer", margin: 12 }}
          onClick={handlePrevious}
        />
        {isPlaying ? (
          <IoMdPause
            style={{ cursor: "pointer", margin: 12 }}
            onClick={() => (!isPlaying ? handlePlay() : handlePause())}
          />
        ) : (
          <IoMdPlay
            style={{ cursor: "pointer", margin: 12 }}
            onClick={() => (!isPlaying ? handlePlay() : handlePause())}
          />
        )}
        <IoMdSkipForward
          style={{ cursor: "pointer", margin: 12 }}
          onClick={handleSkip}
        />
      </div>
    </div>
  );
}

mikhael28 avatar May 30 '22 22:05 mikhael28

Nevermind - it's Safari. It works perfectly, but not on Safari. I guess that's a bug worth reporting too eh?

mikhael28 avatar May 30 '22 22:05 mikhael28

Indeed this feature is not working on Safari and to be honest I was not aware of that. Thanks for bringing it up @mikhael28!

I will investigate this issue in the next few days, maybe there is a solution for that. As far as I understood, Safari does not handle the end AudioContext event, which we use to move the playlist to the next audio (https://github.com/EvandroLG/ts-audio/blob/master/src/playlist/playAudio.ts#L19). There are other ways to do that, so I am confident that we can create a cross-browser solution for this feature! :)

EvandroLG avatar Jun 06 '22 07:06 EvandroLG

That sounds like a solid solution - I want to reiterate how much I like the simplicity of your package. In case you are curious how it’s being used, my open-source project is at https://github.com/mikhael28/paretOS

It’s a ‘high level’ operating system for human performance, and our goal is to include the software that is most helpful and beneficial for people learning new skills, or trying to perform at the highest level in their current occupations. It’s a bit of a broad mandate, but the underlying ethos is to include the 20% of software that is genuinely useful - and leave the junk out. Your audio player was added as a proof of concept for a simple music player, that people can run in the background while doing their work - using public domain jazz music at the moment, but we will add support for playlists like classical and deep house when we have a chance. Maybe even death metal, some people love that for work music. 28B05014-D2BB-4DAB-9111-A1F8C13420FE

mikhael28 avatar Jun 06 '22 18:06 mikhael28

Hi 👋 , @EvandroLG has the safari issue been solved?

ordinz avatar Jan 08 '23 05:01 ordinz

At this point, I might want to look into any 'conditional-render-if-safari' packages, because there are so many places where Safari mucks up the works.

mikhael28 avatar Jan 09 '23 00:01 mikhael28

Heu @ordinz and @mikhael28 Unfortunately, I didn't find a solution for this bug yet 😞 Sorry for not keeping you posted here, but my initial assumption about this issue was incorrect and I don't have a good explanation for why this autoplay feature is not working on Safari. To be honest, I'm unsure if there is a solution for that or if it's an issue related to the internal implementation on Safari. Let's keep this issue open anyway in case someone else has a clue about how to solve it on Safari 👊

EvandroLG avatar Jan 09 '23 20:01 EvandroLG

Heu @ordinz and @mikhael28 Unfortunately, I didn't find a solution for this bug yet 😞 Sorry for not keeping you posted here, but my initial assumption about this issue was incorrect and I don't have a good explanation for why this autoplay feature is not working on Safari. To be honest, I'm unsure if there is a solution for that or if it's an issue related to the internal implementation on Safari. Let's keep this issue open anyway in case someone else has a clue about how to solve it on Safari 👊

Thank you @EvandroLG for the update, I really appreciate it.

ordinz avatar Jan 10 '23 03:01 ordinz