What may be going is that the Elm compiler recognizes we don’t use a return value, so it completely eliminates even calling this function.
Here’s an example:
port module Audio exposing (..)
import Browser
import Html exposing (Html , audio , button , div , h1 , text)
import Html.Attributes exposing (controls, id, src, style)
import Html.Events exposing (onClick)
import Task exposing (succeed)
exampleFile = "fsf.ogg"
run : msg -> Cmd msg
run m =
Task.perform (always m) (Task.succeed ())
-- MAIN
main : Program () Model Msg
main =
Browser.element
{ init = \_ -> init
, view = view
, update = update
, subscriptions = \_ -> Sub.none
}
-- PORTS
port playMusic : () -> Cmd msg
port setSource : String -> Cmd msg
-- MODEL
type alias Model =
{ song : String
}
init : ( Model, Cmd Msg )
init =
( { song = "" }
, Cmd.none
)
-- UPDATE
type Msg
= Play (Maybe String)
| Set String
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Play mf ->
case mf of
Nothing ->
( model
, playMusic ()
)
Just f ->
{-- Attempt 0
let
_ = setSource exampleFile
in
( model
, playMusic ()
)
--}
{-- Attempt 1
let
(m, _ ) = update (Set f) model
in
( model
, playMusic ()
)
--}
run (Set f)
|>
(\r ->
( model
, playMusic ()
)
)
Set message ->
( { model | song = message }
, setSource message
)
-- VIEW
view : Model -> Html Msg
view model =
div []
[ h1 [ id "song-header" ] [ text ("Current song: " ++ model.song) ]
, div [ Html.Attributes.class "song-holder" ]
[ mkButton (Set "song1.mp3") "Song 1"
, mkButton (Set exampleFile) "Song 2"
, mkButton (Set "song3.mp3") "Song 3"
]
, div [ Html.Attributes.class "audio-holder" ]
[ mkButton (Play Nothing) "Play"
, mkButton (Play (Just exampleFile)) "Play Example File"
]
, audio [ src "./song3.mp3", id "audio-player", controls True ] []
]
mkButton : Msg -> String -> Html Msg
mkButton msg text =
button
[ onClick msg
, style "padding" "0.5rem"
, style "margin" "0.3rem"
, style "background" "grey"
]
[ Html.text text ]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Elm</title>
<script src="audio.js"></script>
<link href="index.css" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<script>
var app = Elm.Audio.init
(
{ node: document.getElementById('app')
}
);
document.getElementById("audio-player").volume = 0.2;
app.ports.playMusic.subscribe(function() {
document.getElementById("audio-player").play();
});
app.ports.setSource.subscribe(function(source) {
console.log(`Setting source to ${source}`);
document.getElementById("audio-player").setAttribute("src", source);
});
</script>
</body>
</html>
Basically Play (Just "Somefile.mp3")
should call setSource
first, but Elm never calls this function.
Calling setSource file
on its own does work as expected.
Did anyone run into this issue? If so how did you solve it?