Skip to main content

Crate mediaplayer

Crate mediaplayer 

Source
Expand description

§mediaplayer-rs

Safe Rust bindings for Apple’s MediaPlayer.framework on macOS.

Status: v0.3.0 adds a Tier-2 async stream module (async feature) wrapping six notification / delegate / command-target surfaces as executor-agnostic BoundedAsyncStream<T> event streams. v0.2.0 covers the macOS-available now-playing, remote-command, language-option, and artwork APIs, and exposes explicit macOS-unavailable wrappers for the iOS-only MPMediaLibrary, MPMediaQuery, MPMusicPlayer, MPMediaItem, MPMediaItemCollection, MPMediaPlaylist, MPVolumeView, MPSystemMusicPlayer, and MPPlayableContentDataSource areas.

§Async streams (async feature)

Enable with features = ["async"]:

mediaplayer = { version = "0.3", features = ["async"] }
Stream typeApple surface
NowPlayingItemChangeStreamMPMusicPlayerControllerNowPlayingItemDidChangeNotification
PlaybackStateChangeStreamMPMusicPlayerControllerPlaybackStateDidChangeNotification
VolumeChangeStreamMPMusicPlayerControllerVolumeDidChangeNotification
MediaLibraryChangeStreamMPMediaLibraryDidChangeNotification
RemoteCommandStreamMPRemoteCommandCenter command targets (20 commands)
NowPlayingSessionStreamMPNowPlayingSession delegate (stub; unavailable on macOS)
use mediaplayer::async_api::RemoteCommandStream;
use mediaplayer::remote_commands::Command;

let stream = RemoteCommandStream::subscribe(Command::Play, 16);
while let Some(event) = stream.next().await {
    println!("play at t={:.3}", event.timestamp);
}

§Quick start

use std::time::UNIX_EPOCH;

use mediaplayer::prelude::*;

fn main() {
    let subtitles = LanguageOption::new(
        LanguageOptionType::Legible,
        Some("en"),
        &["public.legible"],
        "English Subtitles",
        "subtitles-en",
    )
    .unwrap();

    let subtitle_group = LanguageOptionGroup::new(&[subtitles.clone()], Some(0), true).unwrap();

    let center = NowPlayingInfoCenter::default_center();
    let info = NowPlayingInfo::new()
        .title("My Song")
        .artist("doom-fish")
        .album_title("Tests")
        .playback_duration(300.0)
        .elapsed_playback_time(0.0)
        .playback_rate(1.0)
        .default_playback_rate(1.0)
        .playback_queue_index(0)
        .playback_queue_count(1)
        .available_language_option_groups(vec![subtitle_group])
        .current_language_options(vec![subtitles])
        .current_playback_date(UNIX_EPOCH)
        .media_type(NowPlayingMediaType::Audio);

    center.set_now_playing_info(&info);
    center.set_playback_state(PlaybackState::Playing);

    let remote = RemoteCommandCenter::shared();
    remote.play_command().set_enabled(true);
    remote.skip_forward_command().set_preferred_intervals(&[15.0, 30.0]);
    remote.change_playback_rate_command().set_supported_playback_rates(&[1.0, 1.5, 2.0]);

    let _play = remote.on_play(|_| HandlerStatus::Success);
    let _rating = remote.on_rating(|event| {
        println!("rating event = {:?}", event.rating);
        HandlerStatus::Success
    });

    center.clear();
}

§Highlights

  • NowPlayingInfoCenter — fluent NowPlayingInfo builder covering queue state, playback progress, language options, service identifiers, live-stream flags, and playback dates.
  • LanguageOption / LanguageOptionGroup — wrappers for MPNowPlayingInfoLanguageOption and MPNowPlayingInfoLanguageOptionGroup.
  • RemoteCommandCenter — zero-cost command handles for base, skip-interval, feedback, rating, playback-rate, shuffle, repeat, and language-option commands.
  • CommandToken — RAII guard that deregisters closures on drop.
  • ArtworkMPMediaItemArtwork from file paths, plus bounds inspection.
  • Explicit macOS stubsMediaLibrary, MediaQuery, MusicPlayer, MediaItem, MediaItemCollection, MediaPlaylist, VolumeView, SystemMusicPlayer, and PlayableContentDataSource all report the Apple availability reason instead of failing mysteriously.

§Example matrix

cargo run --example 01_now_playing_smoke
cargo run --example 02_remote_command_center_smoke
cargo run --example 03_artwork_smoke
cargo run --example 04_media_library_unavailable
cargo run --example 05_media_query_unavailable
cargo run --example 06_music_player_unavailable
cargo run --example 07_media_item_unavailable
cargo run --example 08_media_item_collection_unavailable
cargo run --example 09_media_playlist_unavailable
cargo run --example 10_volume_view_unavailable
cargo run --example 11_system_music_player_unavailable
cargo run --example 12_playable_content_data_source_unavailable

§Verification

cargo clippy --all-targets -- -D warnings
cargo test
for ex in examples/*.rs; do cargo run --example "$(basename "$ex" .rs)"; done

§License

Licensed under either of Apache-2.0 or MIT at your option.

Re-exports§

pub use artwork::AnimatedArtwork;
pub use artwork::Artwork;
pub use content_item::ContentItem;
pub use error::ErrorCode;
pub use error::MediaPlayerError;
pub use error::ERROR_DOMAIN;
pub use media_item::MediaEntityPersistentId;
pub use media_item::MediaItem;
pub use media_item::MediaType;
pub use media_item_collection::MediaItemCollection;
pub use media_library::MediaLibrary;
pub use media_playlist::MediaPlaylist;
pub use media_query::MediaQuery;
pub use music_player::MusicPlayer;
pub use now_playing::LanguageOption;
pub use now_playing::LanguageOptionGroup;
pub use now_playing::LanguageOptionType;
pub use now_playing::NowPlayingInfo;
pub use now_playing::NowPlayingInfoCenter;
pub use now_playing::NowPlayingMediaType;
pub use now_playing::PlaybackState;
pub use playable_content_data_source::PlayableContentDataSource;
pub use remote_commands::ChangePlaybackPositionCommand;
pub use remote_commands::ChangePlaybackRateCommand;
pub use remote_commands::ChangeRepeatModeCommand;
pub use remote_commands::ChangeShuffleModeCommand;
pub use remote_commands::Command;
pub use remote_commands::CommandEvent;
pub use remote_commands::CommandToken;
pub use remote_commands::FeedbackCommand;
pub use remote_commands::HandlerStatus;
pub use remote_commands::LanguageOptionSetting;
pub use remote_commands::RatingCommand;
pub use remote_commands::RemoteCommand;
pub use remote_commands::RemoteCommandCenter;
pub use remote_commands::RepeatType;
pub use remote_commands::SeekType;
pub use remote_commands::ShuffleType;
pub use remote_commands::SkipIntervalCommand;
pub use system_music_player::SystemMusicPlayer;
pub use volume_view::VolumeView;

Modules§

artwork
MPMediaItemArtwork and MPMediaItemAnimatedArtwork wrappers.
async_apiasync
Async stream API for MediaPlayer.framework.
constants
Symbolic MediaPlayer string constants exposed by MediaPlayer.framework.
content_item
Wrapper for MPContentItem.
error
ffi
media_item
MPMediaType plus the explicit macOS-unavailable MPMediaItem marker.
media_item_collection
Explicit macOS-unavailable wrapper for MPMediaItemCollection.
media_library
Explicit macOS-unavailable wrapper for MPMediaLibrary.
media_playlist
Explicit macOS-unavailable wrapper for MPMediaPlaylist.
media_query
Explicit macOS-unavailable wrapper for MPMediaQuery.
music_player
Explicit macOS-unavailable wrapper for MPMusicPlayer.
now_playing
Wrapper for MPNowPlayingInfoCenter and related now-playing metadata types.
playable_content_data_source
Explicit macOS-unavailable wrapper for MPPlayableContentDataSource.
prelude
remote_commands
Wrapper for MPRemoteCommandCenter and associated command types.
system_music_player
Explicit macOS-unavailable wrapper for MPSystemMusicPlayer.
volume_view
Explicit macOS-unavailable wrapper for MPVolumeView.