Skip to content

Commit

Permalink
getTimePlayed & and progress example
Browse files Browse the repository at this point in the history
  • Loading branch information
Giesch committed Oct 27, 2024
1 parent 0ab7aca commit c25a1db
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 28 deletions.
37 changes: 18 additions & 19 deletions examples/music.roc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ init : Task Model []
init =
RocRay.initWindow! { title: "Music" }

# uncomment this to test music deinit:
# _track = Music.load! "examples/assets/music/benny-hill.mp3"
track = Music.load! "examples/assets/music/benny-hill.mp3"

Task.ok { track, trackState: Stopped }
Expand All @@ -37,8 +39,12 @@ render = \model, _state ->
_ ->
Task.ok newModel

draw : Model -> Task {} []
draw = \_model ->
draw : Model -> Task {} _
draw = \model ->
timePlayed = Music.getTimePlayed! model.track
length = Music.length model.track
progress = timePlayed / length

Draw.draw! White \{} ->
Draw.text! {
text: "Music should be playing!",
Expand All @@ -58,28 +64,21 @@ draw = \_model ->
border : F32
border = 1.0

# border (to be drawn over)
Draw.rectangle! {
rect: {
x: bar.x - border,
y: bar.y - border,
width: bar.width + border * 2,
height: bar.height + border * 2,
},
color: Black,
# border (as rect to be drawn over)
borderRect = {
x: bar.x - border,
y: bar.y - border,
width: bar.width + border * 2,
height: bar.height + border * 2,
}
Draw.rectangle! { rect: borderRect, color: Black }

# background
Draw.rectangle! {
rect: bar,
color: Silver,
}
Draw.rectangle! { rect: bar, color: Silver }

# progress
Draw.rectangle! {
rect: { bar & width: bar.width },
color: Red,
}
progressRect = { bar & width: bar.width * progress }
Draw.rectangle! { rect: progressRect, color: Red }

Draw.text! {
text: "PRESS SPACE TO RESTART MUSIC",
Expand Down
3 changes: 3 additions & 0 deletions platform/Effect.roc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ hosted Effect
loadFileToStr,
loadMusicStream,
playMusicStream,
getMusicTimePlayed,
]
imports []

Expand Down Expand Up @@ -105,6 +106,8 @@ Music := Box {}
LoadedMusic : { music : Music, lenSeconds : F32 }
loadMusicStream : Str -> Task LoadedMusic {}
playMusicStream : Music -> Task {} {}
# NOTE the Str (instead of {}) in this error type is to work around a compiler bug
getMusicTimePlayed : Music -> Task F32 Str

RenderTexture := Box {}
createRenderTexture : RocVector2 -> Task RenderTexture {}
Expand Down
21 changes: 18 additions & 3 deletions platform/Music.roc
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
module [Music, load, play, length]
module [Music, load, play, length, getTimePlayed]

import Effect
import RocRay

## A loaded music stream, used to play audio.
Music := Effect.LoadedMusic
Expand All @@ -10,6 +9,7 @@ Music := Effect.LoadedMusic
## ```
## track = Music.load! "resources/green-hill-zone.wav"
## ```
## maps to Raylib's LoadMusicStream
load : Str -> Task Music *
load = \path ->
Effect.loadMusicStream path
Expand All @@ -20,12 +20,27 @@ load = \path ->
## ```
## Music.play! track
## ```
## maps to Raylib's PlayMusicStream
play : Music -> Task {} *
play = \@Music { music } ->
Effect.playMusicStream music
|> Task.mapErr \{} -> crash "unreachable Music.play"

## The length of the track in seconds
## The length of the track in seconds.
## ```
## Music.length track
## ```
## maps to Raylib's GetMusicTimeLength
length : Music -> F32
length = \@Music { lenSeconds } ->
lenSeconds

## Get the time played so far in seconds.
## ```
## Music.getTimePlayed! track
## ```
## maps to Raylib's GetMusicTimePlayed
getTimePlayed : Music -> Task F32 *
getTimePlayed = \@Music { music } ->
Effect.getMusicTimePlayed music
|> Task.mapErr \_fakeStr -> crash "unreachable Music.getTimePlayed"
18 changes: 17 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use platform_mode::PlatformEffect;
use roc::LoadedMusic;
use roc_std::{RocBox, RocList, RocRefcounted, RocResult, RocStr};
use roc_std::{RocBox, RocList, RocResult, RocStr};
use roc_std_heap::ThreadSafeRefcountedResourceHeap;
use std::array;
use std::ffi::{c_int, CString};
Expand Down Expand Up @@ -627,6 +627,22 @@ extern "C" fn roc_fx_playMusicStream(boxed_music: RocBox<()>) -> RocResult<(), (
RocResult::ok(())
}

// NOTE: the RocStr in this error type is to work around a compiler bug
#[no_mangle]
extern "C" fn roc_fx_getMusicTimePlayed(boxed_music: RocBox<()>) -> RocResult<f32, RocStr> {
// TODO does this need a separate permissions enum? maybe rename this one to reuse it?
if let Err(msg) = platform_mode::update(PlatformEffect::PlayMusicStream) {
exit_with_msg(msg, ExitErrCode::ExitEffectNotPermitted);
}

let music: &mut bindings::Music =
ThreadSafeRefcountedResourceHeap::box_to_resource(boxed_music);

let time_played = unsafe { bindings::GetMusicTimePlayed(*music) };

RocResult::ok(time_played)
}

#[no_mangle]
extern "C" fn roc_fx_loadTexture(file_path: &RocStr) -> RocResult<RocBox<()>, ()> {
if let Err(msg) = platform_mode::update(PlatformEffect::LoadTexture) {
Expand Down
3 changes: 2 additions & 1 deletion src/roc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ pub unsafe extern "C" fn roc_dealloc(c_ptr: *mut c_void, _alignment: u32) {

let music_heap = music_heap();
if music_heap.in_range(c_ptr) {
// TODO call deinit_music_stream
println!("roc_dealloc music: {c_ptr:#?}");
deinit_music_stream(c_ptr);
music_heap.dealloc(c_ptr);
return;
}
Expand Down
19 changes: 15 additions & 4 deletions src/roc/music_heap.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::hash::Hash;
use std::cell::RefCell;
use std::os::raw::c_void;
use std::sync::OnceLock;
use std::{cell::RefCell, fmt::Pointer};

use roc_std::{RocBox, RocRefcounted};
use roc_std_heap::ThreadSafeRefcountedResourceHeap;
Expand Down Expand Up @@ -60,12 +59,24 @@ pub fn alloc_music_stream(music: bindings::Music) -> Result<LoadedMusic, ()> {
}

pub(super) unsafe fn deinit_music_stream(c_ptr: *mut c_void) {
println!("deinit_music_stream");
let roc_box = MUSIC_STREAMS.with_borrow_mut(|streams| {
let index_to_drop = streams
.iter_mut()
.enumerate()
.find(|(_index, roc_box)| {
// TODO compare with c_ptr
.find(|(_index, _roc_box)| {
// let is_this_it = {
// // // copied from box_to_resource; this doesn't match c_ptr
// // let box_ptr: usize = unsafe { std::mem::transmute(roc_box) };
// // (box_ptr - std::mem::size_of::<usize>()) as *mut c_void
// };

// println!("c_ptr: {c_ptr:#?}");
// println!("is_this_it: {is_this_it:#?}");

// c_ptr == i_think_this_is_it

// TODO compare roc_box with c_ptr correctly
true
})
.map(|(index, _roc_box)| index)
Expand Down

0 comments on commit c25a1db

Please sign in to comment.