Added UI to switch between transport types at runtime! Needs to be

converted to a ListOverlay, but it works!
This commit is contained in:
casey langen 2016-12-27 01:07:29 -08:00
parent 9c9b003dab
commit 153f12326c
13 changed files with 318 additions and 19 deletions

View File

@ -362,7 +362,7 @@ void CrossfadeTransport::PlayerContext::Reset(
this->canFade = this->started = false;
this->output = url.size() ? outputs::SelectedOutput() : nullptr;
this->player = url.size() ? Player::Create(url, this->output, listener) : nullptr;
this->player = url.size() ? Player::Create(url, this->output, Player::Drain, listener) : nullptr;
}
void CrossfadeTransport::PlayerContext::TransferTo(PlayerContext& to) {

View File

@ -86,7 +86,7 @@ void GaplessTransport::PrepareNextTrack(const std::string& trackUrl) {
{
LockT lock(this->stateMutex);
RESET_NEXT_PLAYER(this);
this->nextPlayer = Player::Create(trackUrl, this->output, this);
this->nextPlayer = Player::Create(trackUrl, this->output, Player::NoDrain, this);
startNext = this->nextCanStart;
}
@ -98,7 +98,7 @@ void GaplessTransport::PrepareNextTrack(const std::string& trackUrl) {
void GaplessTransport::Start(const std::string& url) {
musik::debug::info(TAG, "we were asked to start the track at " + url);
Player* newPlayer = Player::Create(url, this->output, this);
Player* newPlayer = Player::Create(url, this->output, Player::NoDrain, this);
musik::debug::info(TAG, "Player created successfully");
this->StartWithPlayer(newPlayer);

View File

@ -109,14 +109,16 @@ namespace musik {
Player* Player::Create(
const std::string &url,
std::shared_ptr<IOutput> output,
FinishMode finishMode,
EventListener *listener)
{
return new Player(url, output, listener);
return new Player(url, output, finishMode, listener);
}
Player::Player(
const std::string &url,
std::shared_ptr<IOutput> output,
FinishMode finishMode,
EventListener *listener)
: state(Player::Precache)
, url(url)
@ -124,6 +126,7 @@ Player::Player(
, output(output)
, notifiedStarted(false)
, setPosition(-1)
, finishMode(finishMode)
, fftContext(nullptr) {
musik::debug::info(TAG, "new instance created");
@ -370,7 +373,9 @@ void musik::core::audio::playerThreadLoop(Player* player) {
}
/* buffers have been written, wait for the output to play them all */
player->output->Drain();
if (player->finishMode == Player::Drain) {
player->output->Drain();
}
if (!player->Exited()) {
for (Listener* l : player->Listeners()) {

View File

@ -52,6 +52,8 @@ namespace musik { namespace core { namespace audio {
class Player : public musik::core::sdk::IBufferProvider {
public:
enum FinishMode { Drain, NoDrain };
struct EventListener {
virtual void OnPlayerPrepared(Player *player) { }
virtual void OnPlayerStarted(Player *player) { }
@ -65,6 +67,7 @@ namespace musik { namespace core { namespace audio {
static Player* Create(
const std::string &url,
std::shared_ptr<musik::core::sdk::IOutput> output,
FinishMode finishMode,
EventListener *listener);
virtual void OnBufferProcessed(musik::core::sdk::IBuffer *buffer);
@ -89,6 +92,7 @@ namespace musik { namespace core { namespace audio {
Player(
const std::string &url,
std::shared_ptr<musik::core::sdk::IOutput> output,
FinishMode finishMode,
EventListener *listener);
virtual ~Player();
@ -144,6 +148,7 @@ namespace musik { namespace core { namespace audio {
bool notifiedStarted;
float* spectrum;
uint64 samplesWritten;
FinishMode finishMode;
FftContext* fftContext;
};

View File

@ -48,6 +48,7 @@ namespace musik { namespace core { namespace prefs {
const std::string keys::Volume = "Volume";
const std::string keys::RepeatMode = "RepeatMode";
const std::string keys::OutputPlugin = "OutputPlugin";
const std::string keys::Transport = "Transport";
} } }

View File

@ -52,6 +52,7 @@ namespace musik { namespace core { namespace prefs {
extern const std::string Volume;
extern const std::string RepeatMode;
extern const std::string OutputPlugin;
extern const std::string Transport;
}
} } }

View File

@ -47,10 +47,9 @@
#include <app/util/Hotkeys.h>
#include <app/util/PreferenceKeys.h>
#include <app/service/PlaybackService.h>
#include <app/audio/MasterTransport.h>
#include <core/library/LibraryFactory.h>
#include <core/audio/GaplessTransport.h>
#include <core/audio/CrossfadeTransport.h>
#include <core/support/PreferenceKeys.h>
#include <core/audio/Visualizer.h>
@ -65,6 +64,7 @@
#undef MOUSE_MOVED
#endif
using namespace musik::box::audio;
using namespace musik::core;
using namespace musik::core::audio;
using namespace musik::box;
@ -110,8 +110,7 @@ int main(int argc, char* argv[])
LibraryPtr library = LibraryFactory::Libraries().at(0);
//GaplessTransport transport;
CrossfadeTransport transport;
MasterTransport transport;
PlaybackService playback(library, transport);
GlobalHotkeys globalHotkeys(playback, library);
@ -129,7 +128,7 @@ int main(int argc, char* argv[])
Layout libraryLayout(new LibraryLayout(playback, library));
Layout consoleLayout(new ConsoleLayout(transport, library));
Layout settingsLayout(new SettingsLayout(library, playback.GetTransport()));
Layout settingsLayout(new SettingsLayout(library, transport));
Main mainLayout(new MainLayout());

View File

@ -0,0 +1,163 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#include <stdafx.h>
#include "MasterTransport.h"
#include <core/audio/GaplessTransport.h>
#include <core/audio/CrossfadeTransport.h>
#include <core/support/Preferences.h>
#include <core/support/PreferenceKeys.h>
using namespace musik::box::audio;
using namespace musik::core::audio;
using namespace musik::core;
using namespace musik::core::prefs;
using namespace musik::core::sdk;
MasterTransport::MasterTransport()
: prefs(Preferences::ForComponent(components::Playback)) {
this->type = (Type) this->prefs->GetInt(keys::Transport, Gapless);
this->SwitchTo(this->type);
}
MasterTransport::~MasterTransport() {
}
void MasterTransport::SwitchTo(Type type) {
if (!this->transport || this->type != type) {
this->type = type;
this->prefs->SetInt(keys::Transport, (int) this->type);
switch (this->type) {
case Gapless:
this->transport.reset(new GaplessTransport());
break;
case Crossfade:
this->transport.reset(new CrossfadeTransport());
break;
}
this->transport->PlaybackEvent.connect(
this, &MasterTransport::OnPlaybackEvent);
this->transport->StreamEvent.connect(
this, &MasterTransport::OnStreamEvent);
this->transport->TimeChanged.connect(
this, &MasterTransport::OnTimeChanged);
this->transport->VolumeChanged.connect(
this, &MasterTransport::OnVolumeChanged);
}
}
MasterTransport::Type MasterTransport::GetType() {
return this->type;
}
void MasterTransport::PrepareNextTrack(const std::string& trackUrl) {
this->transport->PrepareNextTrack(trackUrl);
}
void MasterTransport::Start(const std::string& trackUrl) {
this->transport->Start(trackUrl);
}
void MasterTransport::Stop() {
this->transport->Stop();
}
bool MasterTransport::Pause() {
return this->transport->Pause();
}
bool MasterTransport::Resume() {
return this->transport->Resume();
}
double MasterTransport::Position() {
return this->transport->Position();
}
void MasterTransport::SetPosition(double seconds) {
this->transport->SetPosition(seconds);
}
double MasterTransport::Volume() {
return this->transport->Volume();
}
void MasterTransport::SetVolume(double volume) {
this->transport->SetVolume(volume);
}
double MasterTransport::GetDuration() {
return this->transport->GetDuration();
}
bool MasterTransport::IsMuted() {
return this->transport->IsMuted();
}
void MasterTransport::SetMuted(bool muted) {
this->transport->SetMuted(muted);
}
void MasterTransport::ReloadOutput() {
this->transport->ReloadOutput();
}
PlaybackState MasterTransport::GetPlaybackState() {
return this->transport->GetPlaybackState();
}
void MasterTransport::OnStreamEvent(int type, std::string url) {
this->StreamEvent(type, url);
}
void MasterTransport::OnPlaybackEvent(int type) {
this->PlaybackEvent(type);
}
void MasterTransport::OnVolumeChanged() {
this->VolumeChanged();
}
void MasterTransport::OnTimeChanged(double time) {
this->TimeChanged(time);
}

View File

@ -0,0 +1,86 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include <core/audio/ITransport.h>
#include <core/support/Preferences.h>
namespace musik { namespace box { namespace audio {
class MasterTransport :
public sigslot::has_slots<>,
public musik::core::audio::ITransport
{
public:
enum Type { Gapless, Crossfade };
MasterTransport();
virtual ~MasterTransport();
virtual void PrepareNextTrack(const std::string& trackUrl);
virtual void Start(const std::string& trackUrl);
virtual void Stop();
virtual bool Pause();
virtual bool Resume();
virtual double Position();
virtual void SetPosition(double seconds);
virtual double Volume();
virtual void SetVolume(double volume);
virtual double GetDuration();
virtual bool IsMuted();
virtual void SetMuted(bool muted);
virtual void ReloadOutput();
virtual musik::core::sdk::PlaybackState GetPlaybackState();
void SwitchTo(Type type);
Type GetType();
private:
void OnStreamEvent(int type, std::string url);
void OnPlaybackEvent(int type);
void OnVolumeChanged();
void OnTimeChanged(double time);
std::shared_ptr<musik::core::audio::ITransport> transport;
std::shared_ptr<musik::core::Preferences> prefs;
Type type;
};
} } }

View File

@ -60,6 +60,7 @@ using namespace musik::core::audio;
using namespace musik::core::library::constants;
using namespace musik::core::sdk;
using namespace musik::box;
using namespace musik::box::audio;
using namespace cursespp;
using namespace std::placeholders;
@ -84,7 +85,7 @@ static bool showDotfiles = false;
SettingsLayout::SettingsLayout(
musik::core::LibraryPtr library,
musik::core::audio::ITransport& transport)
musik::box::audio::MasterTransport& transport)
: LayoutBase()
, library(library)
, indexer(library->Indexer())
@ -134,6 +135,17 @@ void SettingsLayout::OnOutputDropdownActivated(cursespp::TextLabel* label) {
});
}
void SettingsLayout::OnTransportDropdownActivate(cursespp::TextLabel* label) {
if (this->transport.GetType() == MasterTransport::Crossfade) {
this->transport.SwitchTo(MasterTransport::Gapless);
}
else {
this->transport.SwitchTo(MasterTransport::Crossfade);
}
this->LoadPreferences();
}
void SettingsLayout::OnLayout() {
int x = this->GetX(), y = this->GetY();
int cx = this->GetWidth(), cy = this->GetHeight();
@ -154,7 +166,8 @@ void SettingsLayout::OnLayout() {
this->addedPathsList->MoveAndResize(rightX, pathListsY, rightWidth, pathsHeight);
this->outputDropdown->MoveAndResize(1, BOTTOM(this->browseList), cx - 1, LABEL_HEIGHT);
this->dotfileCheckbox->MoveAndResize(1, BOTTOM(this->outputDropdown), cx - 1, LABEL_HEIGHT);
this->transportDropdown->MoveAndResize(1, BOTTOM(this->outputDropdown), cx - 1, LABEL_HEIGHT);
this->dotfileCheckbox->MoveAndResize(1, BOTTOM(this->transportDropdown), cx - 1, LABEL_HEIGHT);
this->removeCheckbox->MoveAndResize(1, BOTTOM(this->dotfileCheckbox), cx - 1, LABEL_HEIGHT);
this->focusShortcutsCheckbox->MoveAndResize(1, BOTTOM(this->removeCheckbox), cx - 1, LABEL_HEIGHT);
this->customColorsCheckbox->MoveAndResize(1, BOTTOM(this->focusShortcutsCheckbox), cx - 1, LABEL_HEIGHT);
@ -231,6 +244,9 @@ void SettingsLayout::InitializeWindows() {
this->outputDropdown.reset(new TextLabel());
this->outputDropdown->Activated.connect(this, &SettingsLayout::OnOutputDropdownActivated);
this->transportDropdown.reset(new TextLabel());
this->transportDropdown->Activated.connect(this, &SettingsLayout::OnTransportDropdownActivate);
CREATE_CHECKBOX(this->dotfileCheckbox, "show dotfiles in directory browser");
CREATE_CHECKBOX(this->removeCheckbox, "remove missing files from library");
CREATE_CHECKBOX(this->focusShortcutsCheckbox, "esc key focuses shortcuts bar");
@ -243,17 +259,19 @@ void SettingsLayout::InitializeWindows() {
this->browseList->SetFocusOrder(0);
this->addedPathsList->SetFocusOrder(1);
this->outputDropdown->SetFocusOrder(2);
this->dotfileCheckbox->SetFocusOrder(3);
this->removeCheckbox->SetFocusOrder(4);
this->focusShortcutsCheckbox->SetFocusOrder(5);
this->customColorsCheckbox->SetFocusOrder(6);
this->hotkeyInput->SetFocusOrder(7);
this->transportDropdown->SetFocusOrder(4);
this->dotfileCheckbox->SetFocusOrder(5);
this->removeCheckbox->SetFocusOrder(6);
this->focusShortcutsCheckbox->SetFocusOrder(7);
this->customColorsCheckbox->SetFocusOrder(8);
this->hotkeyInput->SetFocusOrder(9);
this->AddWindow(this->browseLabel);
this->AddWindow(this->addedPathsLabel);
this->AddWindow(this->browseList);
this->AddWindow(this->addedPathsList);
this->AddWindow(this->outputDropdown);
this->AddWindow(this->transportDropdown);
this->AddWindow(this->dotfileCheckbox);
this->AddWindow(this->removeCheckbox);
this->AddWindow(this->focusShortcutsCheckbox);
@ -319,6 +337,13 @@ void SettingsLayout::LoadPreferences() {
if (output) {
this->outputDropdown->SetText(arrow + " output device: " + output->Name());
}
std::string transportName =
this->transport.GetType() == MasterTransport::Gapless
? "gapless"
: "crossfade";
this->transportDropdown->SetText(arrow + " playback transport: " + transportName);
}
void SettingsLayout::AddSelectedDirectory() {

View File

@ -45,6 +45,7 @@
#include <app/window/TrackListView.h>
#include <app/service/PlaybackService.h>
#include <app/model/DirectoryAdapter.h>
#include <app/audio/MasterTransport.h>
#include <core/library/ILibrary.h>
#include <core/support/Preferences.h>
@ -66,7 +67,7 @@ namespace musik {
public:
SettingsLayout(
musik::core::LibraryPtr library,
musik::core::audio::ITransport& transport);
musik::box::audio::MasterTransport& transport);
virtual ~SettingsLayout();
@ -92,6 +93,7 @@ namespace musik {
cursespp::Checkbox* checkbox, bool checked);
void OnOutputDropdownActivated(cursespp::TextLabel* label);
void OnTransportDropdownActivate(cursespp::TextLabel* label);
int64 ListItemDecorator(
cursespp::ScrollableWindow* w,
@ -101,12 +103,13 @@ namespace musik {
musik::core::LibraryPtr library;
musik::core::IIndexer* indexer;
musik::core::audio::ITransport& transport;
musik::box::audio::MasterTransport& transport;
std::shared_ptr<musik::core::Preferences> libraryPrefs;
std::shared_ptr<musik::core::Preferences> playbackPrefs;
std::shared_ptr<cursespp::TextLabel> outputDropdown;
std::shared_ptr<cursespp::TextLabel> transportDropdown;
std::shared_ptr<cursespp::Checkbox> removeCheckbox;
std::shared_ptr<cursespp::Checkbox> dotfileCheckbox;

View File

@ -119,6 +119,7 @@
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="app\audio\MasterTransport.cpp" />
<ClCompile Include="app\layout\BrowseLayout.cpp" />
<ClCompile Include="app\layout\LibraryLayout.cpp" />
<ClCompile Include="app\layout\ConsoleLayout.cpp" />
@ -174,6 +175,7 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="app\audio\MasterTransport.h" />
<ClInclude Include="app\layout\BrowseLayout.h" />
<ClInclude Include="app\layout\ITopLevelLayout.h" />
<ClInclude Include="app\layout\LibraryLayout.h" />

View File

@ -147,6 +147,9 @@
<ClCompile Include="app\util\Win32Util.cpp">
<Filter>app\util</Filter>
</ClCompile>
<ClCompile Include="app\audio\MasterTransport.cpp">
<Filter>app\audio</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
@ -342,6 +345,9 @@
<ClInclude Include="app\util\Win32Util.h">
<Filter>app\util</Filter>
</ClInclude>
<ClInclude Include="app\audio\MasterTransport.h">
<Filter>app\audio</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="cursespp">
@ -371,5 +377,8 @@
<Filter Include="app\overlay">
<UniqueIdentifier>{a84f242d-d70b-49e9-975e-63fc73954a2b}</UniqueIdentifier>
</Filter>
<Filter Include="app\audio">
<UniqueIdentifier>{b1b3ddc5-b30f-4668-8267-c32cdf3e4da0}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>