From 7708779b9fd4eeef6b04279260e88af8fac0a5b7 Mon Sep 17 00:00:00 2001 From: Chris McCord Date: Wed, 10 Nov 2021 14:29:53 -0500 Subject: [PATCH] Auto advance to next song via client --- assets/js/app.js | 5 +++++ lib/live_beats/media_library.ex | 30 ++++++++++++++++++++++++++ lib/live_beats_web/live/player_live.ex | 7 ++++++ 3 files changed, 42 insertions(+) diff --git a/assets/js/app.js b/assets/js/app.js index a6c6a9a..849a104 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -78,6 +78,11 @@ Hooks.AudioPlayer = { updateProgress(){ if(isNaN(this.player.duration)){ return false } + if(this.player.currentTime >= this.player.duration){ + this.pushEvent("next-song-auto") + clearInterval(this.progressTimer) + return + } this.progress.style.width = `${(this.player.currentTime / (this.player.duration) * 100)}%` this.duration.innerText = this.formatTime(this.player.duration) this.currentTime.innerText = this.formatTime(this.player.currentTime) diff --git a/lib/live_beats/media_library.ex b/lib/live_beats/media_library.ex index 7ae0912..01980a7 100644 --- a/lib/live_beats/media_library.ex +++ b/lib/live_beats/media_library.ex @@ -10,6 +10,7 @@ defmodule LiveBeats.MediaLibrary do alias Ecto.{Multi, Changeset} @pubsub LiveBeats.PubSub + @auto_next_threshold_seconds 5 defdelegate stopped?(song), to: Song defdelegate playing?(song), to: Song @@ -81,6 +82,16 @@ defmodule LiveBeats.MediaLibrary do Phoenix.PubSub.broadcast!(@pubsub, topic(song.user_id), {:pause, song}) end + def play_next_song_auto(user_id) do + song = get_current_active_song(user_id) || get_first_song(user_id) + + if song && elapsed_playback(song) >= song.duration - @auto_next_threshold_seconds do + song + |> get_next_song() + |> play_song() + end + end + defp topic(user_id), do: "room:#{user_id}" def store_mp3(%Song{} = song, tmp_path) do @@ -90,6 +101,7 @@ defmodule LiveBeats.MediaLibrary do def put_stats(%Ecto.Changeset{} = changeset, %MP3Stat{} = stat) do chset = Song.put_duration(changeset, stat.duration) + if error = chset.errors[:duration] do {:error, %{duration: error}} else @@ -166,6 +178,24 @@ defmodule LiveBeats.MediaLibrary do def get_song!(id), do: Repo.get!(Song, id) + def get_first_song(user_id) do + Repo.one( + from s in Song, + where: s.user_id == ^user_id, + order_by: [asc: s.inserted_at, asc: s.id], + limit: 1 + ) + end + + def get_next_song(%Song{} = song) do + Repo.one( + from s in Song, + where: s.user_id == ^song.user_id and s.id > ^song.id, + order_by: [asc: s.inserted_at, asc: s.id], + limit: 1 + ) || get_first_song(song.user_id) + end + def create_song(attrs \\ %{}) do %Song{} |> Song.changeset(attrs) diff --git a/lib/live_beats_web/live/player_live.ex b/lib/live_beats_web/live/player_live.ex index 308b073..c0bfe96 100644 --- a/lib/live_beats_web/live/player_live.ex +++ b/lib/live_beats_web/live/player_live.ex @@ -135,6 +135,13 @@ defmodule LiveBeatsWeb.PlayerLive do end end + def handle_event("next-song-auto", _, socket) do + if socket.assigns.song do + MediaLibrary.play_next_song_auto(socket.assigns.song.user_id) + end + {:noreply, socket} + end + def handle_info(:play_current, socket) do # we raced a pubsub, noop if socket.assigns.song do