diff options
author | Till Mayer <till.mayer@web.de> | 2019-11-04 19:45:19 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-11-04 20:55:46 +0100 |
commit | 77f3c12dc98d68c04e4b87efe35ad05ecd40ef8e (patch) | |
tree | 615ac96aedd446ee54a04c678d7e0f22b62b1b10 /Applications/SoundPlayer/PlaybackManager.cpp | |
parent | 2f13517a1adb262dbda8e12cb0aeb7383bf0c812 (diff) | |
download | serenity-77f3c12dc98d68c04e4b87efe35ad05ecd40ef8e.zip |
SoundPlayer: Added playback controls
The playback of a file can now be paused, stopped, continued and the
user can seek to any part of the file.
Diffstat (limited to 'Applications/SoundPlayer/PlaybackManager.cpp')
-rw-r--r-- | Applications/SoundPlayer/PlaybackManager.cpp | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/Applications/SoundPlayer/PlaybackManager.cpp b/Applications/SoundPlayer/PlaybackManager.cpp new file mode 100644 index 0000000000..c83263ca8b --- /dev/null +++ b/Applications/SoundPlayer/PlaybackManager.cpp @@ -0,0 +1,134 @@ +#include "PlaybackManager.h" + +PlaybackManager::PlaybackManager(NonnullRefPtr<AClientConnection> connection, AWavLoader& loader) + : m_loader(loader) + , m_connection(connection) +{ + m_total_length = loader.total_samples() / static_cast<float>(loader.sample_rate()); + m_timer = CTimer::construct(100, [&]() { next_buffer(); }); + pause(); +} + +PlaybackManager::~PlaybackManager() +{ +} + +void PlaybackManager::stop() +{ + set_paused(true); + m_connection->clear_buffer(true); + m_buffers.clear(); + m_loader.reset(); + m_last_seek = 0; + m_next_buffer = nullptr; + m_current_buffer = nullptr; + m_next_ptr = 0; +} + +void PlaybackManager::play() +{ + set_paused(false); +} + +void PlaybackManager::seek(const int position) +{ + m_last_seek = position; + bool paused_state = m_paused; + set_paused(true); + + m_connection->clear_buffer(true); + m_next_buffer = nullptr; + m_current_buffer = nullptr; + m_next_ptr = 0; + m_buffers.clear(); + m_loader.seek(position); + + if (!paused_state) + set_paused(false); +} + +void PlaybackManager::pause() +{ + set_paused(true); +} + +void PlaybackManager::remove_dead_buffers() +{ + int id = m_connection->get_playing_buffer(); + int current_id = -1; + if (m_current_buffer) + current_id = m_current_buffer->shared_buffer_id(); + + if (id >= 0 && id != current_id) { + while (!m_buffers.is_empty()) { + --m_next_ptr; + auto buffer = m_buffers.take_first(); + + if (buffer->shared_buffer_id() == id) { + m_current_buffer = buffer; + break; + } + } + } +} + +void PlaybackManager::load_next_buffer() +{ + if (m_buffers.size() < 10) { + for (int i = 0; i < 20 && m_loader.loaded_samples() < m_loader.total_samples(); i++) { + auto buffer = m_loader.get_more_samples(PLAYBACK_MANAGER_BUFFER_SIZE); + if (buffer) + m_buffers.append(buffer); + } + } + + if (m_next_ptr < m_buffers.size()) { + m_next_buffer = m_buffers.at(m_next_ptr++); + } else { + m_next_buffer = nullptr; + } +} + +void PlaybackManager::set_paused(bool paused) +{ + if (!m_next_buffer) + load_next_buffer(); + + m_paused = paused; + m_connection->set_paused(paused); +} + +bool PlaybackManager::toggle_pause() +{ + if (m_paused) { + play(); + } else { + pause(); + } + return m_paused; +} + +void PlaybackManager::next_buffer() +{ + if (on_update) + on_update(); + + if (m_paused) + return; + + remove_dead_buffers(); + if (!m_next_buffer) { + if (!m_connection->get_remaining_samples() && !m_paused) { + dbg() << "Exhausted samples :^)"; + stop(); + } + + return; + } + + bool enqueued = m_connection->try_enqueue(*m_next_buffer); + if (!enqueued) + return; + + load_next_buffer(); +} |