A music player that connects to your cloud/distributed storage.
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

Show time and duration after hovering over the progress bar for a while

+100 -37
+31 -5
src/Applications/UI.elm
··· 140 140 , audioHasStalled : Bool 141 141 , audioIsLoading : Bool 142 142 , audioIsPlaying : Bool 143 + , audioPosition : Float 143 144 144 145 -- 145 146 , progress : Dict String Float 146 147 , rememberProgress : Bool 148 + , showTime : Bool 147 149 148 150 ----------------------------------------- 149 151 -- Children ··· 191 193 , audioHasStalled = False 192 194 , audioIsLoading = False 193 195 , audioIsPlaying = False 196 + , audioPosition = 0 194 197 195 198 -- 196 199 , progress = Dict.empty 197 200 , rememberProgress = True 201 + , showTime = False 198 202 199 203 -- Children 200 204 ----------- ··· 253 257 | SetAudioHasStalled Bool 254 258 | SetAudioIsLoading Bool 255 259 | SetAudioIsPlaying Bool 260 + | SetAudioPosition Float 261 + | SetShowTime Bool 256 262 | Stop 257 263 ----------------------------------------- 258 264 -- Authentication ··· 493 499 494 500 SetAudioIsPlaying isPlaying -> 495 501 return { model | audioIsPlaying = isPlaying } 502 + 503 + SetAudioPosition position -> 504 + return { model | audioPosition = position } 505 + 506 + SetShowTime bool -> 507 + return { model | showTime = bool } 496 508 497 509 Stop -> 498 510 returnWithModel model (Ports.pause ()) ··· 920 932 ToggleRememberProgress -> 921 933 translateReply SaveSettings { model | rememberProgress = not model.rememberProgress } 922 934 935 + ToggleTimeDisplay switch -> 936 + switch 937 + == On 938 + |> SetShowTime 939 + |> Debouncer.provideInput 940 + |> Debounce 941 + |> updateWithModel model 942 + 923 943 ----------------------------------------- 924 944 -- Authentication 925 945 ----------------------------------------- ··· 1675 1695 , Ports.setAudioHasStalled SetAudioHasStalled 1676 1696 , Ports.setAudioIsLoading SetAudioIsLoading 1677 1697 , Ports.setAudioIsPlaying SetAudioIsPlaying 1698 + , Ports.setAudioPosition SetAudioPosition 1678 1699 1679 1700 -- Remote 1680 1701 --------- ··· 1990 2011 -- Controls 1991 2012 ----------------------------------------- 1992 2013 , Html.map Reply 1993 - (Lazy.lazy6 1994 - UI.Console.view 2014 + (UI.Console.view 1995 2015 model.queue.activeItem 1996 2016 model.queue.repeat 1997 2017 model.queue.shuffle 1998 - model.audioHasStalled 1999 - model.audioIsLoading 2000 - model.audioIsPlaying 2018 + { stalled = model.audioHasStalled 2019 + , loading = model.audioIsLoading 2020 + , playing = model.audioIsPlaying 2021 + } 2022 + ( model.audioPosition 2023 + , model.audioDuration 2024 + ) 2025 + { showTime = model.showTime 2026 + } 2001 2027 ) 2002 2028 ] 2003 2029
+60 -8
src/Applications/UI/Console.elm
··· 3 3 import Chunky exposing (..) 4 4 import Color 5 5 import Color.Ext as Color 6 + import Common exposing (Switch(..)) 6 7 import Conditional exposing (..) 7 8 import Css 8 9 import Css.Ext as Css ··· 28 29 -- 🗺 29 30 30 31 31 - view : Maybe Queue.Item -> Bool -> Bool -> Bool -> Bool -> Bool -> Html Reply 32 - view activeQueueItem repeat shuffle hasStalled isLoading isPlaying = 32 + view : Maybe Queue.Item -> Bool -> Bool -> { stalled : Bool, loading : Bool, playing : Bool } -> ( Float, Float ) -> { showTime : Bool } -> Html Reply 33 + view activeQueueItem repeat shuffle { stalled, loading, playing } ( position, duration ) { showTime } = 33 34 brick 34 35 [ css consoleStyles ] 35 36 [ T.mt1, T.tc, T.w_100 ] ··· 44 45 , T.pt3 45 46 , T.white 46 47 ] 47 - [ if hasStalled then 48 + [ if stalled then 48 49 slab 49 50 Html.span 50 51 [] 51 52 [ T.dib ] 52 53 [ text "Audio connection got interrupted, trying to reconnect ..." ] 53 54 54 - else if isLoading then 55 + else if loading then 55 56 text "Loading track ..." 56 57 58 + else if showTime && Maybe.isJust activeQueueItem then 59 + let 60 + minutes = 61 + floor (position / 60) 62 + 63 + seconds = 64 + max 0 (floor position - minutes * 60) 65 + 66 + m = 67 + minutes 68 + |> String.fromInt 69 + |> String.padLeft 2 '0' 70 + 71 + s = 72 + seconds 73 + |> String.fromInt 74 + |> String.padLeft 2 '0' 75 + 76 + totalMinutes = 77 + floor (duration / 60) 78 + 79 + totalSeconds = 80 + max 0 (floor duration - totalMinutes * 60) 81 + 82 + tm = 83 + totalMinutes 84 + |> String.fromInt 85 + |> String.padLeft 2 '0' 86 + 87 + ts = 88 + totalSeconds 89 + |> String.fromInt 90 + |> String.padLeft 2 '0' 91 + in 92 + raw 93 + [ text (m ++ ":" ++ s) 94 + , inline [ T.dib, T.mh1 ] [ text "of" ] 95 + , text (tm ++ ":" ++ ts) 96 + ] 97 + 57 98 else 58 99 case Maybe.map .identifiedTrack activeQueueItem of 59 100 Just ( _, { tags } ) -> ··· 71 112 ----------------------------------------- 72 113 -- Progress Bar 73 114 ----------------------------------------- 74 - , brick 75 - [ on "click" (clickLocationDecoder Seek) ] 115 + , let 116 + progress = 117 + if duration <= 0 then 118 + 0 119 + 120 + else 121 + (position / duration) * 100 122 + in 123 + brick 124 + [ on "click" (clickLocationDecoder Seek) 125 + , Html.Styled.Events.onMouseOver (ToggleTimeDisplay On) 126 + , Html.Styled.Events.onMouseOut (ToggleTimeDisplay Off) 127 + ] 76 128 [ T.pointer 77 129 , T.pv1 78 130 ] ··· 80 132 [ css progressBarStyles ] 81 133 [ T.br1 ] 82 134 [ brick 83 - [ css progressBarInnerStyles, style "width" "0" ] 135 + [ css progressBarInnerStyles, style "width" (String.fromFloat progress ++ "%") ] 84 136 [ "progressBarValue" ] 85 137 [] 86 138 ] ··· 100 152 ] 101 153 [ button "Toggle repeat" (smallLight repeat) (icon Icons.repeat 18) ToggleRepeat 102 154 , button "Play previous track" lightPlaceHolder (icon Icons.fast_rewind 20) RewindQueue 103 - , button "" (largeLight isPlaying) play TogglePlayPause 155 + , button "" (largeLight playing) play TogglePlayPause 104 156 , button "Play next track" lightPlaceHolder (icon Icons.fast_forward 20) ShiftQueue 105 157 , button "Toggle shuffle" (smallLight shuffle) (icon Icons.shuffle 18) ToggleShuffle 106 158 ]
+4 -1
src/Applications/UI/Ports.elm
··· 1 - port module UI.Ports exposing (activeQueueItemChanged, activeQueueItemEnded, adjustEqualizerSetting, copyToClipboard, fromAlien, giveBrain, noteProgress, nudgeBrain, pause, pickAverageBackgroundColor, play, preloadAudio, requestNext, requestPlayPause, requestPrevious, requestStop, seek, setAudioDuration, setAudioHasStalled, setAudioIsLoading, setAudioIsPlaying, setAverageBackgroundColor, setIsOnline, setRepeat, showErrorNotification, toBrain) 1 + port module UI.Ports exposing (..) 2 2 3 3 import Alien 4 4 import Json.Encode as Json ··· 65 65 66 66 67 67 port showErrorNotification : (String -> msg) -> Sub msg 68 + 69 + 70 + port setAudioPosition : (Float -> msg) -> Sub msg 68 71 69 72 70 73 port setAudioDuration : (Float -> msg) -> Sub msg
+1
src/Applications/UI/Reply.elm
··· 27 27 | Seek Float 28 28 | TogglePlayPause 29 29 | ToggleRememberProgress 30 + | ToggleTimeDisplay Switch 30 31 ----------------------------------------- 31 32 -- Authentication 32 33 -----------------------------------------
+3 -22
src/Javascript/audio-engine.js
··· 151 151 152 152 // reset 153 153 orchestrion.app.ports.setAudioHasStalled.send(false) 154 + orchestrion.app.ports.setAudioPosition.send(0) 154 155 clearTimeout(orchestrion.unstallTimeout) 155 - setProgressBarWidth(0) 156 156 didShowNetworkError = false 157 157 timesStalled = 0 158 158 ··· 347 347 isNaN(node.duration) || 348 348 isNaN(node.currentTime) || 349 349 node.duration === 0) { 350 - return setProgressBarWidth(0) 350 + return this.app.ports.setAudioPosition.send(0) 351 351 } 352 352 353 - const progress = node.currentTime / node.duration 354 - 355 - setProgressBarWidth(progress) 353 + this.app.ports.setAudioPosition.send(node.currentTime) 356 354 357 355 if (navigator.mediaSession && navigator.mediaSession.setPositionState) { 358 356 navigator.mediaSession.setPositionState({ ··· 476 474 477 475 node.load() 478 476 node.currentTime = time 479 - } 480 - 481 - 482 - 483 - // Progress Bar 484 - // ------------ 485 - 486 - let progressBarNode 487 - 488 - export function setProgressBarWidth(float) { 489 - if (!progressBarNode || !progressBarNode.offsetParent) { 490 - progressBarNode = document.querySelector(".progressBarValue") 491 - } 492 - 493 - if (progressBarNode) { 494 - progressBarNode.style.width = (float * 100).toString() + "%" 495 - } 496 477 } 497 478 498 479
+1 -1
src/Javascript/index.js
··· 83 83 audioEngine.insertTrack(orchestrion, item) 84 84 } else { 85 85 app.ports.setAudioIsPlaying.send(false) 86 - audioEngine.setProgressBarWidth(0) 86 + app.ports.setAudioPosition.send(0) 87 87 } 88 88 }) 89 89