Merge pull request #251 from gwilymk/let-doctests-run

Let doctests run
This commit is contained in:
Gwilym Kuiper 2022-07-12 15:18:49 +01:00 committed by GitHub
commit 241e8b369e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 289 additions and 43 deletions

View file

@ -4,7 +4,7 @@
use agb::fixnum::Num; use agb::fixnum::Num;
use agb::input::{Button, ButtonController, Tri}; use agb::input::{Button, ButtonController, Tri};
use agb::sound::mixer::SoundChannel; use agb::sound::mixer::SoundChannel;
use agb::{include_wav, Gba, fixnum::num}; use agb::{fixnum::num, include_wav, Gba};
// Music - "Dead Code" by Josh Woodward, free download at http://joshwoodward.com // Music - "Dead Code" by Josh Woodward, free download at http://joshwoodward.com
const DEAD_CODE: &[u8] = include_wav!("examples/JoshWoodward-DeadCode.wav"); const DEAD_CODE: &[u8] = include_wav!("examples/JoshWoodward-DeadCode.wav");

BIN
agb/examples/sfx/jump.wav Normal file

Binary file not shown.

BIN
agb/examples/sfx/my_bgm.wav Normal file

Binary file not shown.

View file

@ -20,9 +20,38 @@ use crate::{
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```rust,no_run
/// let backdrop = InfiniteScrolledMap::new( /// # #![no_std]
/// background.background(Priority::P2, RegularBackgroundSize::Background32x32), /// # #![no_main]
/// extern crate alloc;
///
/// use alloc::boxed::Box;
///
/// use agb::display::tiled::{
/// InfiniteScrolledMap,
/// TileSetting,
/// RegularBackgroundSize,
/// TileSet,
/// TileFormat,
/// };
/// use agb::display::Priority;
///
/// mod tilemap {
/// pub const BACKGROUND_MAP: &[u16] = &[ // Probably load this from a file
/// # 0, 1, 2];
/// pub const WIDTH: i32 = // set it to some width
/// # 12;
/// pub const MAP_TILES: &[u8] = &[ // probably load this from a file
/// # 0];
/// }
///
/// # fn foo(mut gba: agb::Gba) {
/// let (gfx, mut vram) = gba.display.video.tiled0();
///
/// let tileset = TileSet::new(&tilemap::MAP_TILES, TileFormat::FourBpp);
///
/// let mut backdrop = InfiniteScrolledMap::new(
/// gfx.background(Priority::P2, RegularBackgroundSize::Background32x32),
/// Box::new(|pos| { /// Box::new(|pos| {
/// ( /// (
/// &tileset, /// &tileset,
@ -40,6 +69,7 @@ use crate::{
/// backdrop.set_pos(&mut vram, (3, 5).into()); /// backdrop.set_pos(&mut vram, (3, 5).into());
/// backdrop.commit(&mut vram); /// backdrop.commit(&mut vram);
/// backdrop.show(); /// backdrop.show();
/// # }
/// ``` /// ```
pub struct InfiniteScrolledMap<'a> { pub struct InfiniteScrolledMap<'a> {
map: MapLoan<'a, RegularMap>, map: MapLoan<'a, RegularMap>,
@ -83,11 +113,57 @@ impl<'a> InfiniteScrolledMap<'a> {
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```rust,no_run
/// background.init(&mut vram, start_position, || { /// # #![no_std]
/// # #![no_main]
/// # #![no_std]
/// # #![no_main]
/// # extern crate alloc;
/// #
/// # use alloc::boxed::Box;
/// #
/// # use agb::display::tiled::{
/// # InfiniteScrolledMap,
/// # TileSetting,
/// # RegularBackgroundSize,
/// # TileSet,
/// # TileFormat,
/// # };
/// # use agb::display::Priority;
/// #
/// # mod tilemap {
/// # pub const BACKGROUND_MAP: &[u16] = &[0, 1, 2];
/// # pub const WIDTH: i32 = 12;
/// # pub const MAP_TILES: &[u8] = &[0];
/// # }
/// #
/// # fn foo(mut gba: agb::Gba) {
/// # let (gfx, mut vram) = gba.display.video.tiled0();
/// #
/// # let tileset = TileSet::new(&tilemap::MAP_TILES, TileFormat::FourBpp);
/// #
/// # let mut backdrop = InfiniteScrolledMap::new(
/// # gfx.background(Priority::P2, RegularBackgroundSize::Background32x32),
/// # Box::new(|pos| {
/// # (
/// # &tileset,
/// # TileSetting::from_raw(
/// # *tilemap::BACKGROUND_MAP
/// # .get((pos.x + tilemap::WIDTH * pos.y) as usize)
/// # .unwrap_or(&0),
/// # ),
/// # )
/// # }),
/// # );
/// #
/// # let vblank = agb::interrupt::VBlank::get();
/// # let mut mixer = gba.mixer.mixer();
/// let start_position = agb::fixnum::Vector2D::new(10, 10);
/// backdrop.init(&mut vram, start_position, &mut || {
/// vblank.wait_for_vblank(); /// vblank.wait_for_vblank();
/// mixer.frame(); /// mixer.frame();
/// }); /// });
/// # }
/// ``` /// ```
pub fn init( pub fn init(
&mut self, &mut self,
@ -111,11 +187,58 @@ impl<'a> InfiniteScrolledMap<'a> {
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```rust,no_run
/// while background.init_partial(&mut vram, start_position) == PartialUpdateStatus::Continue { /// # #![no_std]
/// # #![no_main]
/// # #![no_std]
/// # #![no_main]
/// # extern crate alloc;
/// #
/// # use alloc::boxed::Box;
/// #
/// # use agb::display::tiled::{
/// # InfiniteScrolledMap,
/// # TileSetting,
/// # RegularBackgroundSize,
/// # TileSet,
/// # TileFormat,
/// # PartialUpdateStatus,
/// # };
/// # use agb::display::Priority;
/// #
/// # mod tilemap {
/// # pub const BACKGROUND_MAP: &[u16] = &[0, 1, 2];
/// # pub const WIDTH: i32 = 12;
/// # pub const MAP_TILES: &[u8] = &[0];
/// # }
/// #
/// # fn foo(mut gba: agb::Gba) {
/// # let (gfx, mut vram) = gba.display.video.tiled0();
/// #
/// # let tileset = TileSet::new(&tilemap::MAP_TILES, TileFormat::FourBpp);
/// #
/// # let mut backdrop = InfiniteScrolledMap::new(
/// # gfx.background(Priority::P2, RegularBackgroundSize::Background32x32),
/// # Box::new(|pos| {
/// # (
/// # &tileset,
/// # TileSetting::from_raw(
/// # *tilemap::BACKGROUND_MAP
/// # .get((pos.x + tilemap::WIDTH * pos.y) as usize)
/// # .unwrap_or(&0),
/// # ),
/// # )
/// # }),
/// # );
/// #
/// # let vblank = agb::interrupt::VBlank::get();
/// # let mut mixer = gba.mixer.mixer();
/// let start_position = agb::fixnum::Vector2D::new(10, 10);
/// while backdrop.init_partial(&mut vram, start_position) == PartialUpdateStatus::Continue {
/// vblank.wait_for_vblank(); /// vblank.wait_for_vblank();
/// mixer.frame(); /// mixer.frame();
/// } /// }
/// # }
/// ``` /// ```
pub fn init_partial( pub fn init_partial(
&mut self, &mut self,

View file

@ -235,10 +235,17 @@ fn interrupt_to_root(interrupt: Interrupt) -> &'static InterruptRoot {
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```rust,no_run
/// let _a = add_interrupt_handler(Interrupt::VBlank, |_: &CriticalSection| { /// # #![no_std]
/// println!("Woah there! There's been a vblank!"); /// # #![no_main]
/// use bare_metal::CriticalSection;
///
/// # fn foo() {
/// # use agb::interrupt::{add_interrupt_handler, Interrupt};
/// let _a = add_interrupt_handler(Interrupt::VBlank, |_: CriticalSection| {
/// agb::println!("Woah there! There's been a vblank!");
/// }); /// });
/// # }
/// ``` /// ```
pub fn add_interrupt_handler<'a>( pub fn add_interrupt_handler<'a>(
interrupt: Interrupt, interrupt: Interrupt,

View file

@ -50,7 +50,7 @@
/// ///
/// This will generate something along the lines of the following: /// This will generate something along the lines of the following:
/// ///
/// ``` /// ```rust,ignore
/// // module name comes from the name of the toml file, so `sprites` in this case because it is /// // module name comes from the name of the toml file, so `sprites` in this case because it is
/// // called `sprites.toml` /// // called `sprites.toml`
/// mod sprites { /// mod sprites {
@ -75,7 +75,7 @@
/// ``` /// ```
/// ///
/// In `src/main.rs` /// In `src/main.rs`
/// ``` /// ```rust,ignore
/// mod gfx { /// mod gfx {
/// use agb::display::object::ObjectControl; /// use agb::display::object::ObjectControl;
/// ///
@ -105,7 +105,7 @@
/// ``` /// ```
/// ///
/// In `src/main.rs`: /// In `src/main.rs`:
/// ``` /// ```rust,ignore
/// mod gfx { /// mod gfx {
/// use agb::display::background::BackgroundDistributor; /// use agb::display::background::BackgroundDistributor;
/// ///
@ -139,7 +139,7 @@ macro_rules! include_font {
/// Doing this will ensure that `agb` can correctly set up the environment to call your rust function on start up. /// Doing this will ensure that `agb` can correctly set up the environment to call your rust function on start up.
/// ///
/// # Examples /// # Examples
/// ``` /// ```no_run,rust
/// #![no_std] /// #![no_std]
/// #![no_main] /// #![no_main]
/// ///
@ -206,7 +206,7 @@ static mut GBASINGLE: single::Singleton<Gba> = single::Singleton::new(unsafe { G
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```no_run,rust
/// #![no_std] /// #![no_std]
/// #![no_main] /// #![no_main]
/// ///

View file

@ -35,9 +35,13 @@
//! To create a sound mixer, you will need to get it out of the [`Gba`](crate::Gba) struct //! To create a sound mixer, you will need to get it out of the [`Gba`](crate::Gba) struct
//! as follows: //! as follows:
//! //!
//! ``` //! ```rust,no_run
//! # #![no_std]
//! # #![no_main]
//! # fn foo(gba: &mut agb::Gba) {
//! let mut mixer = gba.mixer.mixer(); //! let mut mixer = gba.mixer.mixer();
//! mixer.enable(); //! mixer.enable();
//! # }
//! ``` //! ```
//! //!
//! ## Doing the per-frame work //! ## Doing the per-frame work
@ -48,22 +52,34 @@
//! //!
//! Without interrupts: //! Without interrupts:
//! //!
//! ``` //! ```rust,no_run
//! # #![no_std]
//! # #![no_main]
//! # fn foo(gba: &mut agb::Gba) {
//! # let mut mixer = gba.mixer.mixer();
//! # let vblank = agb::interrupt::VBlank::get();
//! // Somewhere in your main loop: //! // Somewhere in your main loop:
//! mixer.frame(); //! mixer.frame();
//! vblank.wait_for_vblank(); //! vblank.wait_for_vblank();
//! mixer.after_vblank(); //! mixer.after_vblank();
//! # }
//! ``` //! ```
//! //!
//! Or with interrupts: //! Or with interrupts:
//! //!
//! ``` //! ```rust,no_run
//! # #![no_std]
//! # #![no_main]
//! # fn foo(gba: &mut agb::Gba) {
//! # let mut mixer = gba.mixer.mixer();
//! # let vblank = agb::interrupt::VBlank::get();
//! // outside your main loop, close to initialisation //! // outside your main loop, close to initialisation
//! let _mixer_interrupt = mixer.setup_interrupt_handler(); //! let _mixer_interrupt = mixer.setup_interrupt_handler();
//! //!
//! // inside your main loop //! // inside your main loop
//! mixer.frame(); //! mixer.frame();
//! vblank.wait_for_vblank(); //! vblank.wait_for_vblank();
//! # }
//! ``` //! ```
//! //!
//! Despite being high performance, the mixer still takes a sizable portion of CPU time (6-10% //! Despite being high performance, the mixer still takes a sizable portion of CPU time (6-10%
@ -79,14 +95,21 @@
//! Use the [`include_wav!`](crate::include_wav) macro in order to load the sound. This will produce //! Use the [`include_wav!`](crate::include_wav) macro in order to load the sound. This will produce
//! an error if your wav file is of the wrong frequency. //! an error if your wav file is of the wrong frequency.
//! //!
//! ``` //! ```rust,no_run
//! # #![no_std]
//! # #![no_main]
//! # fn foo(gba: &mut agb::Gba) {
//! # let mut mixer = gba.mixer.mixer();
//! # let vblank = agb::interrupt::VBlank::get();
//! # use agb::{*, sound::mixer::*};
//! // Outside your main function in global scope: //! // Outside your main function in global scope:
//! const MY_CRAZY_SOUND: &[u8] = include_wav!("sfx/my_crazy_sound.wav"); //! const MY_CRAZY_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav");
//! //!
//! // Then to play the sound: //! // Then to play the sound:
//! let mut channel = SoundChannel::new(MY_CRAZY_SOUND); //! let mut channel = SoundChannel::new(MY_CRAZY_SOUND);
//! channel.stereo(); //! channel.stereo();
//! let _ = mixer.play_sound(channel); // we don't mind if this sound doesn't actually play //! let _ = mixer.play_sound(channel); // we don't mind if this sound doesn't actually play
//! # }
//! ``` //! ```
//! //!
//! See the [`SoundChannel`] struct for more details on how you can configure the sounds to play. //! See the [`SoundChannel`] struct for more details on how you can configure the sounds to play.
@ -152,25 +175,39 @@ enum SoundPriority {
/// play regardless of whether you have lots of sound effects playing. You create a high /// play regardless of whether you have lots of sound effects playing. You create a high
/// priority sound channel using [`new_high_priority`](SoundChannel::new_high_priority). /// priority sound channel using [`new_high_priority`](SoundChannel::new_high_priority).
/// ///
/// ``` /// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// # use agb::sound::mixer::*;
/// # use agb::*;
/// // in global scope: /// // in global scope:
/// const MY_BGM: [u8] = include_wav!("sfx/my_bgm.wav"); /// const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav");
/// ///
/// // somewhere in code /// // somewhere in code
/// # fn foo(gba: &mut Gba) {
/// # let mut mixer = gba.mixer.mixer();
/// let mut bgm = SoundChannel::new_high_priority(MY_BGM); /// let mut bgm = SoundChannel::new_high_priority(MY_BGM);
/// bgm.stereo().should_loop(); /// bgm.stereo().should_loop();
/// let _ = mixer.play_sound(bgm); /// let _ = mixer.play_sound(bgm);
/// # }
/// ``` /// ```
/// ///
/// ## Playing a sound effect /// ## Playing a sound effect
/// ///
/// ``` /// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// # use agb::sound::mixer::*;
/// # use agb::*;
/// // in global scope: /// // in global scope:
/// const JUMP_SOUND: [u8] = include_wav!("sfx/jump_sound.wav"); /// const JUMP_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav");
/// ///
/// // somewhere in code /// // somewhere in code
/// let jump_sound = SoundChannel::new(MY_JUMP_SOUND); /// # fn foo(gba: &mut Gba) {
/// # let mut mixer = gba.mixer.mixer();
/// let jump_sound = SoundChannel::new(JUMP_SOUND);
/// let _ = mixer.play_sound(jump_sound); /// let _ = mixer.play_sound(jump_sound);
/// # }
/// ``` /// ```
pub struct SoundChannel { pub struct SoundChannel {
data: &'static [u8], data: &'static [u8],
@ -198,13 +235,20 @@ impl SoundChannel {
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// # use agb::sound::mixer::*;
/// # use agb::*;
/// # fn foo(gba: &mut Gba) {
/// # let mut mixer = gba.mixer.mixer();
/// // in global scope: /// // in global scope:
/// const JUMP_SOUND: [u8] = include_wav!("sfx/jump_sound.wav"); /// const JUMP_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav");
/// ///
/// // somewhere in code /// // somewhere in code
/// let jump_sound = SoundChannel::new(MY_JUMP_SOUND); /// let jump_sound = SoundChannel::new(JUMP_SOUND);
/// let _ = mixer.play_sound(jump_sound); /// let _ = mixer.play_sound(jump_sound);
/// # }
/// ``` /// ```
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
@ -233,14 +277,21 @@ impl SoundChannel {
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// # use agb::sound::mixer::*;
/// # use agb::*;
/// # fn foo(gba: &mut Gba) {
/// # let mut mixer = gba.mixer.mixer();
/// // in global scope: /// // in global scope:
/// const MY_BGM: [u8] = include_wav!("sfx/my_bgm.wav"); /// const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav");
/// ///
/// // somewhere in code /// // somewhere in code
/// let mut bgm = SoundChannel::new_high_priority(MY_BGM); /// let mut bgm = SoundChannel::new_high_priority(MY_BGM);
/// bgm.stereo().should_loop(); /// bgm.stereo().should_loop();
/// let _ = mixer.play_sound(bgm); /// let _ = mixer.play_sound(bgm);
/// # }
/// ``` /// ```
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]

View file

@ -36,15 +36,28 @@ extern "C" {
/// You should not create this struct directly, instead creating it through the [`Gba`](crate::Gba) /// You should not create this struct directly, instead creating it through the [`Gba`](crate::Gba)
/// struct as follows: /// struct as follows:
/// ///
/// ``` /// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// # use agb::sound::mixer::*;
/// # use agb::*;
/// # fn foo(gba: &mut Gba) {
/// let mut mixer = gba.mixer.mixer(); /// let mut mixer = gba.mixer.mixer();
/// # }
/// ``` /// ```
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// # use agb::sound::mixer::*;
/// # use agb::*;
/// # fn foo(gba: &mut Gba) {
/// # let mut mixer = gba.mixer.mixer();
/// # let vblank = agb::interrupt::VBlank::get();
/// // Outside your main function in global scope: /// // Outside your main function in global scope:
/// const MY_CRAZY_SOUND: &[u8] = include_wav!("sfx/my_crazy_sound.wav"); /// const MY_CRAZY_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav");
/// ///
/// // in your main function: /// // in your main function:
/// let mut mixer = gba.mixer.mixer(); /// let mut mixer = gba.mixer.mixer();
@ -57,6 +70,7 @@ extern "C" {
/// vblank.wait_for_vblank(); /// vblank.wait_for_vblank();
/// mixer.after_vblank(); /// mixer.after_vblank();
/// } /// }
/// # }
/// ``` /// ```
pub struct Mixer { pub struct Mixer {
buffer: MixerBuffer, buffer: MixerBuffer,
@ -72,12 +86,20 @@ pub struct Mixer {
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// # use agb::sound::mixer::*;
/// # use agb::*;
/// # fn foo(gba: &mut Gba) {
/// # let mut mixer = gba.mixer.mixer();
/// # const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav");
/// let mut channel = SoundChannel::new_high_priority(MY_BGM); /// let mut channel = SoundChannel::new_high_priority(MY_BGM);
/// let bgm_channel_id = mixer.play_sound(channel).unwrap(); // will always be Some if high priority /// let bgm_channel_id = mixer.play_sound(channel).unwrap(); // will always be Some if high priority
/// ///
/// // Later, stop that particular channel /// // Later, stop that particular channel
/// mixer.channel(bgm_channel_id).stop(); /// mixer.channel(&bgm_channel_id).expect("Expected to still be playing").stop();
/// # }
/// ``` /// ```
pub struct ChannelId(usize, i32); pub struct ChannelId(usize, i32);
@ -106,12 +128,20 @@ impl Mixer {
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// # use agb::sound::mixer::*;
/// # use agb::*;
/// # fn foo(gba: &mut Gba) {
/// # let mut mixer = gba.mixer.mixer();
/// # let vblank = agb::interrupt::VBlank::get();
/// loop { /// loop {
/// mixer.frame(); /// mixer.frame();
/// vblank.wait_for_vblank(); /// vblank.wait_for_vblank();
/// mixer.after_vblank(); /// mixer.after_vblank();
/// } /// }
/// # }
/// ``` /// ```
#[cfg(not(feature = "freq32768"))] #[cfg(not(feature = "freq32768"))]
pub fn after_vblank(&mut self) { pub fn after_vblank(&mut self) {
@ -127,7 +157,14 @@ impl Mixer {
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// # use agb::sound::mixer::*;
/// # use agb::*;
/// # fn foo(gba: &mut Gba) {
/// # let mut mixer = gba.mixer.mixer();
/// # let vblank = agb::interrupt::VBlank::get();
/// // you must set this to a named variable to ensure that the scope is long enough /// // you must set this to a named variable to ensure that the scope is long enough
/// let _mixer_interrupt = mixer.setup_interrupt_handler(); /// let _mixer_interrupt = mixer.setup_interrupt_handler();
/// ///
@ -135,6 +172,7 @@ impl Mixer {
/// mixer.frame(); /// mixer.frame();
/// vblank.wait_for_vblank(); /// vblank.wait_for_vblank();
/// } /// }
/// # }
/// ``` /// ```
pub fn setup_interrupt_handler(&self) -> InterruptHandler<'_> { pub fn setup_interrupt_handler(&self) -> InterruptHandler<'_> {
let mut timer1 = unsafe { Timer::new(1) }; let mut timer1 = unsafe { Timer::new(1) };
@ -157,12 +195,20 @@ impl Mixer {
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// # use agb::sound::mixer::*;
/// # use agb::*;
/// # fn foo(gba: &mut Gba) {
/// # let mut mixer = gba.mixer.mixer();
/// # let vblank = agb::interrupt::VBlank::get();
/// loop { /// loop {
/// mixer.frame(); /// mixer.frame();
/// vblank.wait_for_vblank(); /// vblank.wait_for_vblank();
/// mixer.after_vblank(); // optional, only if not using interrupts /// mixer.after_vblank(); // optional, only if not using interrupts
/// } /// }
/// # }
/// ``` /// ```
pub fn frame(&mut self) { pub fn frame(&mut self) {
if !self.buffer.should_calculate() { if !self.buffer.should_calculate() {
@ -188,9 +234,17 @@ impl Mixer {
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// # use agb::sound::mixer::*;
/// # use agb::*;
/// # fn foo(gba: &mut Gba) {
/// # let mut mixer = gba.mixer.mixer();
/// # const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav");
/// let mut channel = SoundChannel::new_high_priority(MY_BGM); /// let mut channel = SoundChannel::new_high_priority(MY_BGM);
/// let bgm_channel_id = mixer.play_sound(channel).unwrap(); // will always be Some if high priority /// let bgm_channel_id = mixer.play_sound(channel).unwrap(); // will always be Some if high priority
/// # }
/// ``` /// ```
pub fn play_sound(&mut self, new_channel: SoundChannel) -> Option<ChannelId> { pub fn play_sound(&mut self, new_channel: SoundChannel) -> Option<ChannelId> {
for (i, channel) in self.channels.iter_mut().enumerate() { for (i, channel) in self.channels.iter_mut().enumerate() {
@ -229,12 +283,20 @@ impl Mixer {
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```rust,no_run
/// # #![no_std]
/// # #![no_main]
/// # use agb::sound::mixer::*;
/// # use agb::*;
/// # fn foo(gba: &mut Gba) {
/// # let mut mixer = gba.mixer.mixer();
/// # const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav");
/// let mut channel = SoundChannel::new_high_priority(MY_BGM); /// let mut channel = SoundChannel::new_high_priority(MY_BGM);
/// let bgm_channel_id = mixer.play_sound(channel).unwrap(); // will always be Some if high priority /// let bgm_channel_id = mixer.play_sound(channel).unwrap(); // will always be Some if high priority
/// ///
/// // Later, stop that particular channel /// // Later, stop that particular channel
/// mixer.channel(bgm_channel_id).stop(); /// mixer.channel(&bgm_channel_id).expect("Expected still to be playing").stop();
/// # }
/// ``` /// ```
pub fn channel(&mut self, id: &ChannelId) -> Option<&'_ mut SoundChannel> { pub fn channel(&mut self, id: &ChannelId) -> Option<&'_ mut SoundChannel> {
if let Some(channel) = &mut self.channels[id.0] { if let Some(channel) = &mut self.channels[id.0] {

View file

@ -17,6 +17,9 @@ test:
test-release: test-release:
just _test-release agb just _test-release agb
doctest-agb:
(cd agb && cargo test --doc -Z doctest-xcompile)
clean: clean:
just _all-crates _clean just _all-crates _clean
@ -34,7 +37,7 @@ run-game game:
run-game-debug game: run-game-debug game:
(cd "examples/{{game}}" && cargo run) (cd "examples/{{game}}" && cargo run)
ci: build-debug clippy test build-release test-release build-roms build-book ci: build-debug clippy test build-release test-release doctest-agb build-roms build-book
build-roms: build-roms:
just _build-rom "examples/the-purple-night" "PURPLENIGHT" just _build-rom "examples/the-purple-night" "PURPLENIGHT"