Serenity Operating System
at master 165 lines 4.4 kB view raw
1/* 2 * Copyright (c) 2021, Cesar Torres <shortanemoia@protonmail.com> 3 * Copyright (c) 2021, Leandro A. F. Pereira <leandro@tia.mat.br> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#include "Player.h" 9#include <LibAudio/FlacLoader.h> 10#include <LibCore/DeprecatedFile.h> 11 12Player::Player(Audio::ConnectionToServer& audio_client_connection) 13 : m_audio_client_connection(audio_client_connection) 14 , m_playback_manager(audio_client_connection) 15{ 16 m_playback_manager.on_update = [&]() { 17 auto samples_played = m_playback_manager.loader()->loaded_samples(); 18 auto sample_rate = m_playback_manager.loader()->sample_rate(); 19 float source_to_dest_ratio = static_cast<float>(sample_rate) / m_playback_manager.device_sample_rate(); 20 samples_played *= source_to_dest_ratio; 21 22 auto played_seconds = samples_played / sample_rate; 23 time_elapsed(played_seconds); 24 sound_buffer_played(m_playback_manager.current_buffer(), m_playback_manager.device_sample_rate(), samples_played); 25 }; 26 m_playback_manager.on_finished_playing = [&]() { 27 set_play_state(PlayState::Stopped); 28 29 switch (loop_mode()) { 30 case LoopMode::File: 31 play_file_path(loaded_filename()); 32 return; 33 case LoopMode::Playlist: 34 play_file_path(m_playlist.next()); 35 return; 36 case LoopMode::None: 37 return; 38 } 39 }; 40} 41 42void Player::play_file_path(DeprecatedString const& path) 43{ 44 if (path.is_null()) 45 return; 46 47 if (!Core::DeprecatedFile::exists(path)) { 48 audio_load_error(path, "File does not exist"sv); 49 return; 50 } 51 52 if (is_playlist(path)) { 53 playlist_loaded(path, m_playlist.load(path)); 54 return; 55 } 56 57 auto maybe_loader = Audio::Loader::create(path); 58 if (maybe_loader.is_error()) { 59 audio_load_error(path, maybe_loader.error().description); 60 return; 61 } 62 auto loader = maybe_loader.value(); 63 64 m_loaded_filename = path; 65 66 // TODO: The combination of sample count, sample rate, and sample data should be properly abstracted for the source and the playback device. 67 total_samples_changed(loader->total_samples() * (static_cast<float>(loader->sample_rate()) / m_playback_manager.device_sample_rate())); 68 m_playback_manager.set_loader(move(loader)); 69 file_name_changed(path); 70 71 play(); 72} 73 74bool Player::is_playlist(DeprecatedString const& path) 75{ 76 return (path.ends_with(".m3u"sv, AK::CaseSensitivity::CaseInsensitive) 77 || path.ends_with(".m3u8"sv, AK::CaseSensitivity::CaseInsensitive)); 78} 79 80void Player::set_play_state(PlayState state) 81{ 82 if (m_play_state != state) { 83 m_play_state = state; 84 play_state_changed(state); 85 } 86} 87 88void Player::set_loop_mode(LoopMode mode) 89{ 90 if (m_loop_mode != mode) { 91 m_loop_mode = mode; 92 m_playlist.set_looping(mode == LoopMode::Playlist); 93 loop_mode_changed(mode); 94 } 95} 96 97void Player::set_volume(double volume) 98{ 99 m_volume = clamp(volume, 0, 1.5); 100 m_audio_client_connection.set_self_volume(m_volume); 101 volume_changed(m_volume); 102} 103 104void Player::set_mute(bool muted) 105{ 106 if (m_muted != muted) { 107 m_muted = muted; 108 m_audio_client_connection.set_self_muted(muted); 109 mute_changed(muted); 110 } 111} 112 113void Player::set_shuffle_mode(ShuffleMode mode) 114{ 115 if (m_shuffle_mode != mode) { 116 m_shuffle_mode = mode; 117 m_playlist.set_shuffling(mode == ShuffleMode::Shuffling); 118 shuffle_mode_changed(mode); 119 } 120} 121 122void Player::play() 123{ 124 m_playback_manager.play(); 125 set_play_state(PlayState::Playing); 126} 127 128void Player::pause() 129{ 130 m_playback_manager.pause(); 131 set_play_state(PlayState::Paused); 132} 133 134void Player::toggle_pause() 135{ 136 bool paused = m_playback_manager.toggle_pause(); 137 set_play_state(paused ? PlayState::Paused : PlayState::Playing); 138} 139 140void Player::stop() 141{ 142 m_playback_manager.stop(); 143 set_play_state(PlayState::Stopped); 144} 145 146void Player::mute() 147{ 148 set_mute(true); 149} 150 151void Player::toggle_mute() 152{ 153 set_mute(!m_muted); 154} 155 156void Player::seek(int sample) 157{ 158 sample *= (m_playback_manager.device_sample_rate() / static_cast<float>(m_playback_manager.loader()->sample_rate())); 159 m_playback_manager.seek(sample); 160} 161 162Vector<Audio::PictureData> const& Player::pictures() const 163{ 164 return m_playback_manager.loader()->pictures(); 165}