summaryrefslogtreecommitdiff
path: root/Applications/SoundPlayer/PlaybackManager.cpp
diff options
context:
space:
mode:
authorTill Mayer <till.mayer@web.de>2019-11-04 19:45:19 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-11-04 20:55:46 +0100
commit77f3c12dc98d68c04e4b87efe35ad05ecd40ef8e (patch)
tree615ac96aedd446ee54a04c678d7e0f22b62b1b10 /Applications/SoundPlayer/PlaybackManager.cpp
parent2f13517a1adb262dbda8e12cb0aeb7383bf0c812 (diff)
downloadserenity-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.cpp134
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();
+}