mirror of
https://github.com/clangen/musikcube.git
synced 2025-03-14 04:18:36 +00:00
Added the ability for the user to select their preferred output plugin!
This commit is contained in:
parent
3e6f66d986
commit
ae88f6ee31
@ -49,6 +49,12 @@ class AlsaOut : public musik::core::sdk::IOutput {
|
||||
AlsaOut();
|
||||
virtual ~AlsaOut();
|
||||
|
||||
/* IPlugin */
|
||||
virtual const char* Name() { return "AlsaOut IOutput"; }
|
||||
virtual const char* Version() { return "0.3"; }
|
||||
virtual const char* Author() { return "Julian Cromarty, clangen"; }
|
||||
|
||||
/* IOutput */
|
||||
virtual void Destroy();
|
||||
virtual void Pause();
|
||||
virtual void Resume();
|
||||
|
@ -37,15 +37,8 @@
|
||||
#include <core/sdk/IOutput.h>
|
||||
#include "AlsaOut.h"
|
||||
|
||||
class AlsaOutPlugin : public musik::core::sdk::IPlugin {
|
||||
virtual void Destroy() { delete this; };
|
||||
virtual const char* Name() { return "AlsaOut IOutput plugin"; }
|
||||
virtual const char* Version() { return "0.3"; }
|
||||
virtual const char* Author() { return "Julian Cromarty, clangen"; }
|
||||
};
|
||||
|
||||
extern "C" musik::core::sdk::IPlugin* GetPlugin() {
|
||||
return new AlsaOutPlugin();
|
||||
return new AlsaOut();
|
||||
}
|
||||
|
||||
extern "C" musik::core::sdk::IOutput* GetAudioOutput() {
|
||||
|
@ -54,6 +54,13 @@ class CoreAudioOut : public musik::core::sdk::IOutput {
|
||||
CoreAudioOut();
|
||||
virtual ~CoreAudioOut();
|
||||
|
||||
/* IPlugin */
|
||||
void Destroy() { delete this; };
|
||||
const char* Name() { return "CoreAudio IOutput"; };
|
||||
const char* Version() { return "0.2"; };
|
||||
const char* Author() { return "clangen"; };
|
||||
|
||||
/* IOutput */
|
||||
virtual void Destroy();
|
||||
virtual void Pause();
|
||||
virtual void Resume();
|
||||
|
@ -42,21 +42,8 @@
|
||||
#define DLLEXPORT
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
class CoreAudioOutPlugin : public musik::core::sdk::IPlugin {
|
||||
void Destroy() { delete this; };
|
||||
const char* Name() { return "CoreAudio IOutput"; };
|
||||
const char* Version() { return "0.2"; };
|
||||
const char* Author() { return "clangen"; };
|
||||
};
|
||||
|
||||
extern "C" DLLEXPORT musik::core::sdk::IPlugin* GetPlugin() {
|
||||
return new CoreAudioOutPlugin;
|
||||
return new CoreAudioOut();
|
||||
}
|
||||
|
||||
extern "C" DLLEXPORT musik::core::sdk::IOutput* GetAudioOutput() {
|
||||
|
@ -44,6 +44,13 @@ class PulseOut : public musik::core::sdk::IOutput {
|
||||
PulseOut();
|
||||
virtual ~PulseOut();
|
||||
|
||||
/* IPlugin */
|
||||
virtual void Destroy() { delete this; };
|
||||
virtual const char* Name() { return "PulseAudio IOutput plugin"; }
|
||||
virtual const char* Version() { return "0.1"; }
|
||||
virtual const char* Author() { return "clangen"; }
|
||||
|
||||
/* IOutput */
|
||||
virtual void Destroy();
|
||||
virtual void Pause();
|
||||
virtual void Resume();
|
||||
|
@ -37,15 +37,8 @@
|
||||
#include <core/sdk/IOutput.h>
|
||||
#include "PulseOut.h"
|
||||
|
||||
class PulseOutPlugin : public musik::core::sdk::IPlugin {
|
||||
virtual void Destroy() { delete this; };
|
||||
virtual const char* Name() { return "PulseAudio IOutput plugin"; }
|
||||
virtual const char* Version() { return "0.1"; }
|
||||
virtual const char* Author() { return "clangen"; }
|
||||
};
|
||||
|
||||
extern "C" musik::core::sdk::IPlugin* GetPlugin() {
|
||||
return new PulseOutPlugin();
|
||||
return new PulseOut();
|
||||
}
|
||||
|
||||
extern "C" musik::core::sdk::IOutput* GetAudioOutput() {
|
||||
|
@ -61,7 +61,8 @@ WasapiOut::WasapiOut()
|
||||
, audioClock(nullptr)
|
||||
, outputBufferFrames(0)
|
||||
, state(StateStopped)
|
||||
, latency(0) {
|
||||
, latency(0)
|
||||
, volume(1.0f) {
|
||||
ZeroMemory(&waveFormat, sizeof(WAVEFORMATEXTENSIBLE));
|
||||
}
|
||||
|
||||
@ -96,6 +97,7 @@ void WasapiOut::Resume() {
|
||||
void WasapiOut::SetVolume(double volume) {
|
||||
Lock lock(this->stateMutex);
|
||||
|
||||
this->volume = volume;
|
||||
if (this->simpleAudioVolume) {
|
||||
simpleAudioVolume->SetMasterVolume((float) volume, 0);
|
||||
simpleAudioVolume->SetMute(false, 0);
|
||||
@ -309,6 +311,7 @@ bool WasapiOut::Configure(IBuffer *buffer) {
|
||||
}
|
||||
|
||||
this->state = StatePlaying;
|
||||
this->SetVolume(this->volume);
|
||||
|
||||
return true;
|
||||
}
|
@ -52,7 +52,13 @@ class WasapiOut : public IOutput {
|
||||
WasapiOut();
|
||||
~WasapiOut();
|
||||
|
||||
/* IPlugin */
|
||||
const char* Name() { return "Wasapi IOutput"; };
|
||||
const char* Version() { return "0.1"; };
|
||||
const char* Author() { return "clangen"; };
|
||||
virtual void Destroy();
|
||||
|
||||
/* IOutput */
|
||||
virtual void Pause();
|
||||
virtual void Resume();
|
||||
virtual void SetVolume(double volume);
|
||||
@ -81,6 +87,7 @@ class WasapiOut : public IOutput {
|
||||
UINT32 outputBufferFrames;
|
||||
std::atomic<State> state;
|
||||
WAVEFORMATEXTENSIBLE waveFormat;
|
||||
double volume;
|
||||
|
||||
std::recursive_mutex stateMutex;
|
||||
INT64 latency;
|
||||
|
@ -41,15 +41,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
||||
return true;
|
||||
}
|
||||
|
||||
class WasapiOutPlugin : public musik::core::sdk::IPlugin {
|
||||
void Destroy() { delete this; };
|
||||
const char* Name() { return "WASAPI IOutput"; };
|
||||
const char* Version() { return "0.1"; };
|
||||
const char* Author() { return "clangen"; };
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) musik::core::sdk::IPlugin* GetPlugin() {
|
||||
return new WasapiOutPlugin();
|
||||
return new WasapiOut();
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) musik::core::sdk::IOutput* GetAudioOutput() {
|
||||
|
@ -49,7 +49,13 @@ class WaveOut : public IOutput {
|
||||
WaveOut();
|
||||
~WaveOut();
|
||||
|
||||
/* IPlugin */
|
||||
const char* Name() { return "WaveOut IOutput"; };
|
||||
const char* Version() { return "0.4"; };
|
||||
const char* Author() { return "Bj\xC3\xB6rn Olievier, clangen"; };
|
||||
virtual void Destroy();
|
||||
|
||||
/* IOutput */
|
||||
virtual void Pause();
|
||||
virtual void Resume();
|
||||
virtual void SetVolume(double volume);
|
||||
|
@ -41,15 +41,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
||||
return true;
|
||||
}
|
||||
|
||||
class WaveOutPlugin : public musik::core::sdk::IPlugin {
|
||||
void Destroy() { delete this; };
|
||||
const char* Name() { return "WaveOut IOutput"; };
|
||||
const char* Version() { return "0.3"; };
|
||||
const char* Author() { return "Björn Olievier, clangen"; };
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) musik::core::sdk::IPlugin* GetPlugin() {
|
||||
return new WaveOutPlugin();
|
||||
return new WaveOut();
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) musik::core::sdk::IOutput* GetAudioOutput() {
|
||||
|
@ -2,6 +2,7 @@ set(CORE_SOURCES
|
||||
./debug.cpp
|
||||
./audio/Buffer.cpp
|
||||
./audio/GaplessTransport.cpp
|
||||
./audio/Outputs.cpp
|
||||
./audio/Player.cpp
|
||||
./audio/Stream.cpp
|
||||
./audio/Streams.cpp
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <core/debug.h>
|
||||
#include <core/audio/GaplessTransport.h>
|
||||
#include <core/plugin/PluginFactory.h>
|
||||
#include <core/audio/Outputs.h>
|
||||
#include <algorithm>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
@ -57,7 +58,7 @@ GaplessTransport::GaplessTransport()
|
||||
, nextPlayer(nullptr)
|
||||
, nextCanStart(false)
|
||||
, muted(false) {
|
||||
this->output = Player::CreateDefaultOutput();
|
||||
this->output = outputs::SelectedOutput();
|
||||
}
|
||||
|
||||
GaplessTransport::~GaplessTransport() {
|
||||
@ -135,6 +136,12 @@ void GaplessTransport::StartWithPlayer(Player* newPlayer) {
|
||||
}
|
||||
}
|
||||
|
||||
void GaplessTransport::ReloadOutput() {
|
||||
this->Stop();
|
||||
this->output = outputs::SelectedOutput();
|
||||
this->output->SetVolume(volume);
|
||||
}
|
||||
|
||||
void GaplessTransport::Stop() {
|
||||
this->StopInternal(false, true);
|
||||
}
|
||||
|
@ -68,6 +68,8 @@ namespace musik { namespace core { namespace audio {
|
||||
virtual bool IsMuted();
|
||||
virtual void SetMuted(bool muted);
|
||||
|
||||
virtual void ReloadOutput();
|
||||
|
||||
virtual musik::core::sdk::PlaybackState GetPlaybackState();
|
||||
|
||||
private:
|
||||
@ -95,7 +97,7 @@ namespace musik { namespace core { namespace audio {
|
||||
|
||||
musik::core::sdk::PlaybackState state;
|
||||
std::recursive_mutex stateMutex;
|
||||
musik::core::audio::OutputPtr output;
|
||||
std::shared_ptr<musik::core::sdk::IOutput> output;
|
||||
PlayerList active;
|
||||
Player* nextPlayer;
|
||||
double volume;
|
||||
|
@ -65,6 +65,8 @@ namespace musik { namespace core { namespace audio {
|
||||
virtual bool IsMuted() = 0;
|
||||
virtual void SetMuted(bool muted) = 0;
|
||||
|
||||
virtual void ReloadOutput() = 0;
|
||||
|
||||
virtual musik::core::sdk::PlaybackState GetPlaybackState() = 0;
|
||||
};
|
||||
|
||||
|
134
src/core/audio/Outputs.cpp
Normal file
134
src/core/audio/Outputs.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "pch.hpp"
|
||||
#include "Outputs.h"
|
||||
#include <core/plugin/PluginFactory.h>
|
||||
#include <core/support/Preferences.h>
|
||||
#include <core/support/PreferenceKeys.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace musik::core;
|
||||
using namespace musik::core::audio;
|
||||
using namespace musik::core::sdk;
|
||||
using namespace musik::core::prefs;
|
||||
|
||||
using Output = std::shared_ptr<IOutput>;
|
||||
using OutputList = std::vector<Output>;
|
||||
|
||||
#if defined(WIN32)
|
||||
static const std::string defaultOutput = "Wasapi IOutput";
|
||||
#elif defined(__APPLE__)
|
||||
static const std::string defaultOutput = "CoreAudio IOutput";
|
||||
#else
|
||||
static const std::string defaultOutput = "Alsa IOutput";
|
||||
#endif
|
||||
|
||||
#define LOWER(x) std::transform(x.begin(), x.end(), x.begin(), tolower);
|
||||
|
||||
namespace musik {
|
||||
namespace core {
|
||||
namespace audio {
|
||||
namespace outputs {
|
||||
Output FindByName(const std::string& name, const OutputList& list) {
|
||||
if (name.size()) {
|
||||
auto it = list.begin();
|
||||
while (it != list.end()) {
|
||||
if ((*it)->Name() == name) {
|
||||
return (*it);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
return Output();
|
||||
}
|
||||
|
||||
OutputList GetAllOutputs() {
|
||||
using OutputDeleter = PluginFactory::DestroyDeleter<IOutput>;
|
||||
|
||||
OutputList result = PluginFactory::Instance()
|
||||
.QueryInterface<IOutput, OutputDeleter>("GetAudioOutput");
|
||||
|
||||
std::sort(
|
||||
result.begin(),
|
||||
result.end(),
|
||||
[](Output left, Output right) -> bool {
|
||||
std::string l = left->Name();
|
||||
LOWER(l);
|
||||
std::string r = right->Name();
|
||||
LOWER(r);
|
||||
return l < r;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SelectOutput(std::shared_ptr<musik::core::sdk::IOutput> output) {
|
||||
std::shared_ptr<Preferences> prefs =
|
||||
Preferences::ForComponent(components::Playback);
|
||||
|
||||
prefs->SetString(keys::OutputPlugin, output->Name());
|
||||
}
|
||||
|
||||
Output SelectedOutput() {
|
||||
std::shared_ptr<Preferences> prefs =
|
||||
Preferences::ForComponent(components::Playback);
|
||||
|
||||
const OutputList plugins = GetAllOutputs();
|
||||
|
||||
if (plugins.size()) {
|
||||
/* try to find the user selected plugin first */
|
||||
Output result = FindByName(prefs->GetString(keys::OutputPlugin), plugins);
|
||||
|
||||
if (!result) {
|
||||
/* fall back to the default */
|
||||
result = FindByName(defaultOutput, plugins);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
/* no default? ugh, return the first one. */
|
||||
result = plugins[0];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return Output();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
46
src/core/audio/Outputs.h
Normal file
46
src/core/audio/Outputs.h
Normal file
@ -0,0 +1,46 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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/config.h>
|
||||
#include <core/sdk/IOutput.h>
|
||||
|
||||
namespace musik { namespace core { namespace audio { namespace outputs {
|
||||
|
||||
std::vector<std::shared_ptr<musik::core::sdk::IOutput> > GetAllOutputs();
|
||||
void SelectOutput(std::shared_ptr<musik::core::sdk::IOutput> output);
|
||||
std::shared_ptr<musik::core::sdk::IOutput> SelectedOutput();
|
||||
|
||||
} } } }
|
@ -103,26 +103,11 @@ namespace musik {
|
||||
}
|
||||
}
|
||||
|
||||
Player* Player::Create(const std::string &url, OutputPtr output, PlayerEventListener *listener) {
|
||||
Player* Player::Create(const std::string &url, std::shared_ptr<IOutput> output, PlayerEventListener *listener) {
|
||||
return new Player(url, output, listener);
|
||||
}
|
||||
|
||||
OutputPtr Player::CreateDefaultOutput() {
|
||||
/* if no output is specified, find all output plugins, and select the first one. */
|
||||
typedef std::vector<OutputPtr> OutputVector;
|
||||
|
||||
OutputVector outputs = musik::core::PluginFactory::Instance().QueryInterface<
|
||||
IOutput, musik::core::PluginFactory::DestroyDeleter<IOutput> >("GetAudioOutput");
|
||||
|
||||
if (!outputs.empty()) {
|
||||
musik::debug::info(TAG, "found an IOutput device!");
|
||||
return outputs.front();
|
||||
}
|
||||
|
||||
return OutputPtr();
|
||||
}
|
||||
|
||||
Player::Player(const std::string &url, OutputPtr output, PlayerEventListener *listener)
|
||||
Player::Player(const std::string &url, std::shared_ptr<IOutput> output, PlayerEventListener *listener)
|
||||
: state(Player::Precache)
|
||||
, url(url)
|
||||
, currentPosition(0)
|
||||
|
@ -47,9 +47,6 @@
|
||||
|
||||
namespace musik { namespace core { namespace audio {
|
||||
|
||||
class Output;
|
||||
typedef std::shared_ptr<musik::core::sdk::IOutput> OutputPtr;
|
||||
|
||||
struct FftContext;
|
||||
|
||||
class Player : public musik::core::sdk::IBufferProvider {
|
||||
@ -62,11 +59,9 @@ namespace musik { namespace core { namespace audio {
|
||||
virtual void OnPlaybackError(Player *player) = 0;
|
||||
};
|
||||
|
||||
static OutputPtr CreateDefaultOutput();
|
||||
|
||||
static Player* Create(
|
||||
const std::string &url,
|
||||
OutputPtr output,
|
||||
std::shared_ptr<musik::core::sdk::IOutput> output,
|
||||
PlayerEventListener *listener);
|
||||
|
||||
virtual void OnBufferProcessed(musik::core::sdk::IBuffer *buffer);
|
||||
@ -91,7 +86,7 @@ namespace musik { namespace core { namespace audio {
|
||||
|
||||
Player(
|
||||
const std::string &url,
|
||||
OutputPtr output,
|
||||
std::shared_ptr<musik::core::sdk::IOutput> output,
|
||||
PlayerEventListener *listener);
|
||||
|
||||
virtual ~Player();
|
||||
@ -106,7 +101,7 @@ namespace musik { namespace core { namespace audio {
|
||||
Quit = 2
|
||||
} States;
|
||||
|
||||
OutputPtr output;
|
||||
std::shared_ptr<musik::core::sdk::IOutput> output;
|
||||
StreamPtr stream;
|
||||
ThreadPtr thread;
|
||||
BufferList lockedBuffers;
|
||||
|
@ -85,6 +85,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="audio\GaplessTransport.cpp" />
|
||||
<ClCompile Include="audio\Outputs.cpp" />
|
||||
<ClCompile Include="audio\Streams.cpp" />
|
||||
<ClCompile Include="audio\Visualizer.cpp" />
|
||||
<ClCompile Include="debug.cpp" />
|
||||
@ -118,6 +119,7 @@
|
||||
<ClInclude Include="audio\GaplessTransport.h" />
|
||||
<ClInclude Include="audio\IStream.h" />
|
||||
<ClInclude Include="audio\ITransport.h" />
|
||||
<ClInclude Include="audio\Outputs.h" />
|
||||
<ClInclude Include="audio\Streams.h" />
|
||||
<ClInclude Include="audio\Visualizer.h" />
|
||||
<ClInclude Include="debug.h" />
|
||||
|
@ -115,6 +115,9 @@
|
||||
<ClCompile Include="audio\Streams.cpp">
|
||||
<Filter>src\audio</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="audio\Outputs.cpp">
|
||||
<Filter>src\audio</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.hpp">
|
||||
@ -282,5 +285,8 @@
|
||||
<ClInclude Include="audio\Streams.h">
|
||||
<Filter>src\audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="audio\Outputs.h">
|
||||
<Filter>src\audio</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -35,15 +35,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
#include "IPlugin.h"
|
||||
#include "IDataStream.h"
|
||||
#include "IBuffer.h"
|
||||
#include "IBufferProvider.h"
|
||||
|
||||
namespace musik { namespace core { namespace sdk {
|
||||
|
||||
class IOutput {
|
||||
class IOutput : public IPlugin {
|
||||
public:
|
||||
virtual void Destroy() = 0;
|
||||
virtual void Pause() = 0;
|
||||
virtual void Resume() = 0;
|
||||
virtual void SetVolume(double volume) = 0;
|
||||
|
@ -47,6 +47,7 @@ namespace musik { namespace core { namespace prefs {
|
||||
const std::string keys::SyncOnStartup = "SyncOnStartup";
|
||||
const std::string keys::Volume = "Volume";
|
||||
const std::string keys::RepeatMode = "RepeatMode";
|
||||
const std::string keys::OutputPlugin = "OutputPlugin";
|
||||
|
||||
} } }
|
||||
|
||||
|
@ -51,6 +51,7 @@ namespace musik { namespace core { namespace prefs {
|
||||
extern const std::string SyncOnStartup;
|
||||
extern const std::string Volume;
|
||||
extern const std::string RepeatMode;
|
||||
extern const std::string OutputPlugin;
|
||||
}
|
||||
|
||||
} } }
|
||||
|
@ -16,6 +16,7 @@ set (BOX_SRCS
|
||||
./app/query/NowPlayingTrackListQuery.cpp
|
||||
./app/query/SearchTrackListQuery.cpp
|
||||
./app/service/PlaybackService.cpp
|
||||
./app/overlay/OutputOverlay.cpp
|
||||
./app/overlay/VisualizerOverlay.cpp
|
||||
./app/util/Duration.cpp
|
||||
./app/util/Hotkeys.cpp
|
||||
|
@ -126,7 +126,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
Layout libraryLayout(new LibraryLayout(playback, library));
|
||||
Layout consoleLayout(new ConsoleLayout(transport, library));
|
||||
Layout settingsLayout(new SettingsLayout(library));
|
||||
Layout settingsLayout(new SettingsLayout(library, playback.GetTransport()));
|
||||
|
||||
Main mainLayout(new MainLayout());
|
||||
mainLayout->Layout();
|
||||
|
@ -43,18 +43,22 @@
|
||||
#include <core/library/Indexer.h>
|
||||
#include <core/library/LocalLibraryConstants.h>
|
||||
#include <core/support/PreferenceKeys.h>
|
||||
#include <core/audio/Outputs.h>
|
||||
|
||||
#include <app/query/SearchTrackListQuery.h>
|
||||
#include <app/util/Hotkeys.h>
|
||||
#include <app/util/PreferenceKeys.h>
|
||||
#include <app/overlay/OutputOverlay.h>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include "SettingsLayout.h"
|
||||
|
||||
using namespace musik;
|
||||
using namespace musik::core::library::constants;
|
||||
using namespace musik::core;
|
||||
using namespace musik::core::audio;
|
||||
using namespace musik::core::library::constants;
|
||||
using namespace musik::core::sdk;
|
||||
using namespace musik::box;
|
||||
using namespace cursespp;
|
||||
using namespace std::placeholders;
|
||||
@ -75,13 +79,17 @@ using namespace std::placeholders;
|
||||
|
||||
using EntryPtr = IScrollAdapter::EntryPtr;
|
||||
|
||||
static const std::string arrow = "\xe2\x96\xbc";
|
||||
static bool showDotfiles = false;
|
||||
|
||||
SettingsLayout::SettingsLayout(musik::core::LibraryPtr library)
|
||||
SettingsLayout::SettingsLayout(
|
||||
musik::core::LibraryPtr library,
|
||||
musik::core::audio::ITransport& transport)
|
||||
: LayoutBase()
|
||||
, library(library)
|
||||
, indexer(library->Indexer()) {
|
||||
this->prefs = Preferences::ForComponent(core::prefs::components::Settings);
|
||||
, indexer(library->Indexer())
|
||||
, transport(transport) {
|
||||
this->libraryPrefs = Preferences::ForComponent(core::prefs::components::Settings);
|
||||
this->indexer->PathsUpdated.connect(this, &SettingsLayout::RefreshAddedPaths);
|
||||
this->InitializeWindows();
|
||||
}
|
||||
@ -91,8 +99,8 @@ SettingsLayout::~SettingsLayout() {
|
||||
|
||||
void SettingsLayout::OnCheckboxChanged(cursespp::Checkbox* cb, bool checked) {
|
||||
if (cb == removeCheckbox.get()) {
|
||||
this->prefs->SetBool(core::prefs::keys::RemoveMissingFiles, checked);
|
||||
this->prefs->Save();
|
||||
this->libraryPrefs->SetBool(core::prefs::keys::RemoveMissingFiles, checked);
|
||||
this->libraryPrefs->Save();
|
||||
}
|
||||
else if (cb == dotfileCheckbox.get()) {
|
||||
showDotfiles = !showDotfiles;
|
||||
@ -100,15 +108,32 @@ void SettingsLayout::OnCheckboxChanged(cursespp::Checkbox* cb, bool checked) {
|
||||
this->browseList->OnAdapterChanged();
|
||||
}
|
||||
else if (cb == focusShortcutsCheckbox.get()) {
|
||||
this->prefs->SetBool(box::prefs::keys::EscFocusesShortcuts, checked);
|
||||
this->prefs->Save();
|
||||
this->libraryPrefs->SetBool(box::prefs::keys::EscFocusesShortcuts, checked);
|
||||
this->libraryPrefs->Save();
|
||||
}
|
||||
else if (cb == customColorsCheckbox.get()) {
|
||||
this->prefs->SetBool(box::prefs::keys::DisableCustomColors, checked);
|
||||
this->prefs->Save();
|
||||
this->libraryPrefs->SetBool(box::prefs::keys::DisableCustomColors, checked);
|
||||
this->libraryPrefs->Save();
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsLayout::OnOutputDropdownActivated(cursespp::TextLabel* label) {
|
||||
std::string currentName;
|
||||
std::shared_ptr<IOutput> currentPlugin = outputs::SelectedOutput();
|
||||
currentName = currentPlugin ? currentPlugin->Name() : currentName;
|
||||
|
||||
OutputOverlay::Show([this, currentName] {
|
||||
std::string newName;
|
||||
std::shared_ptr<IOutput> newPlugin = outputs::SelectedOutput();
|
||||
newName = newPlugin ? newPlugin->Name() : newName;
|
||||
|
||||
if (currentName != newName) {
|
||||
this->LoadPreferences();
|
||||
this->transport.ReloadOutput();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SettingsLayout::Layout() {
|
||||
int x = this->GetX(), y = this->GetY();
|
||||
int cx = this->GetWidth(), cy = this->GetHeight();
|
||||
@ -128,7 +153,9 @@ void SettingsLayout::Layout() {
|
||||
this->browseList->MoveAndResize(leftX, pathListsY, leftWidth, pathsHeight);
|
||||
this->addedPathsList->MoveAndResize(rightX, pathListsY, rightWidth, pathsHeight);
|
||||
|
||||
this->dotfileCheckbox->MoveAndResize(1, BOTTOM(this->browseList), cx - 1, LABEL_HEIGHT);
|
||||
this->outputDropdown->MoveAndResize(1, BOTTOM(this->browseList), cx - 1, LABEL_HEIGHT);
|
||||
|
||||
this->dotfileCheckbox->MoveAndResize(1, BOTTOM(this->outputDropdown) + 1, 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);
|
||||
@ -202,6 +229,9 @@ void SettingsLayout::InitializeWindows() {
|
||||
this->addedPathsAdapter.SetItemDecorator(decorator);
|
||||
this->browseAdapter.SetItemDecorator(decorator);
|
||||
|
||||
this->outputDropdown.reset(new TextLabel());
|
||||
this->outputDropdown->Activated.connect(this, &SettingsLayout::OnOutputDropdownActivated);
|
||||
|
||||
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");
|
||||
@ -213,16 +243,18 @@ void SettingsLayout::InitializeWindows() {
|
||||
|
||||
this->browseList->SetFocusOrder(0);
|
||||
this->addedPathsList->SetFocusOrder(1);
|
||||
this->dotfileCheckbox->SetFocusOrder(2);
|
||||
this->removeCheckbox->SetFocusOrder(3);
|
||||
this->focusShortcutsCheckbox->SetFocusOrder(4);
|
||||
this->customColorsCheckbox->SetFocusOrder(5);
|
||||
this->hotkeyInput->SetFocusOrder(6);
|
||||
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->AddWindow(this->browseLabel);
|
||||
this->AddWindow(this->addedPathsLabel);
|
||||
this->AddWindow(this->browseList);
|
||||
this->AddWindow(this->addedPathsList);
|
||||
this->AddWindow(this->outputDropdown);
|
||||
this->AddWindow(this->dotfileCheckbox);
|
||||
this->AddWindow(this->removeCheckbox);
|
||||
this->AddWindow(this->focusShortcutsCheckbox);
|
||||
@ -252,7 +284,7 @@ void SettingsLayout::OnVisibilityChanged(bool visible) {
|
||||
}
|
||||
|
||||
void SettingsLayout::CheckShowFirstRunDialog() {
|
||||
if (!this->prefs->GetBool(box::prefs::keys::FirstRunSettingsDisplayed)) {
|
||||
if (!this->libraryPrefs->GetBool(box::prefs::keys::FirstRunSettingsDisplayed)) {
|
||||
std::shared_ptr<DialogOverlay> dialog(new DialogOverlay());
|
||||
|
||||
(*dialog)
|
||||
@ -271,7 +303,7 @@ void SettingsLayout::CheckShowFirstRunDialog() {
|
||||
"ENTER",
|
||||
"ok",
|
||||
[this](std::string key) {
|
||||
this->prefs->SetBool(box::prefs::keys::FirstRunSettingsDisplayed, true);
|
||||
this->libraryPrefs->SetBool(box::prefs::keys::FirstRunSettingsDisplayed, true);
|
||||
});
|
||||
|
||||
App::Overlays().Push(dialog);
|
||||
@ -279,9 +311,14 @@ void SettingsLayout::CheckShowFirstRunDialog() {
|
||||
}
|
||||
|
||||
void SettingsLayout::LoadPreferences() {
|
||||
this->removeCheckbox->SetChecked(this->prefs->GetBool(core::prefs::keys::RemoveMissingFiles, true));
|
||||
this->focusShortcutsCheckbox->SetChecked(this->prefs->GetBool(box::prefs::keys::EscFocusesShortcuts, true));
|
||||
this->customColorsCheckbox->SetChecked(this->prefs->GetBool(box::prefs::keys::DisableCustomColors));
|
||||
this->removeCheckbox->SetChecked(this->libraryPrefs->GetBool(core::prefs::keys::RemoveMissingFiles, true));
|
||||
this->focusShortcutsCheckbox->SetChecked(this->libraryPrefs->GetBool(box::prefs::keys::EscFocusesShortcuts, true));
|
||||
this->customColorsCheckbox->SetChecked(this->libraryPrefs->GetBool(box::prefs::keys::DisableCustomColors));
|
||||
|
||||
std::shared_ptr<IOutput> output = outputs::SelectedOutput();
|
||||
if (output) {
|
||||
this->outputDropdown->SetText(arrow + " output device: " + output->Name());
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsLayout::AddSelectedDirectory() {
|
||||
|
@ -64,7 +64,9 @@ namespace musik {
|
||||
public sigslot::has_slots<>
|
||||
{
|
||||
public:
|
||||
SettingsLayout(musik::core::LibraryPtr library);
|
||||
SettingsLayout(
|
||||
musik::core::LibraryPtr library,
|
||||
musik::core::audio::ITransport& transport);
|
||||
|
||||
virtual ~SettingsLayout();
|
||||
|
||||
@ -87,6 +89,8 @@ namespace musik {
|
||||
void OnCheckboxChanged(
|
||||
cursespp::Checkbox* checkbox, bool checked);
|
||||
|
||||
void OnOutputDropdownActivated(cursespp::TextLabel* label);
|
||||
|
||||
int64 ListItemDecorator(
|
||||
cursespp::ScrollableWindow* w,
|
||||
size_t index,
|
||||
@ -95,8 +99,12 @@ namespace musik {
|
||||
|
||||
musik::core::LibraryPtr library;
|
||||
musik::core::IIndexer* indexer;
|
||||
musik::core::audio::ITransport& transport;
|
||||
|
||||
std::shared_ptr<musik::core::Preferences> prefs;
|
||||
std::shared_ptr<musik::core::Preferences> libraryPrefs;
|
||||
std::shared_ptr<musik::core::Preferences> playbackPrefs;
|
||||
|
||||
std::shared_ptr<cursespp::TextLabel> outputDropdown;
|
||||
|
||||
std::shared_ptr<cursespp::Checkbox> removeCheckbox;
|
||||
std::shared_ptr<cursespp::Checkbox> dotfileCheckbox;
|
||||
|
103
src/musikbox/app/overlay/OutputOverlay.cpp
Normal file
103
src/musikbox/app/overlay/OutputOverlay.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "OutputOverlay.h"
|
||||
|
||||
#include <core/audio/Outputs.h>
|
||||
|
||||
#include <cursespp/App.h>
|
||||
#include <cursespp/SimpleScrollAdapter.h>
|
||||
#include <cursespp/ListOverlay.h>
|
||||
#include <cursespp/DialogOverlay.h>
|
||||
#include <vector>
|
||||
|
||||
using namespace musik::box;
|
||||
using namespace musik::core::audio;
|
||||
using namespace musik::core::sdk;
|
||||
using namespace cursespp;
|
||||
|
||||
static std::vector<std::shared_ptr<IOutput> > plugins;
|
||||
|
||||
static void showNoOutputPluginsMessage() {
|
||||
std::shared_ptr<DialogOverlay> dialog(new DialogOverlay());
|
||||
|
||||
(*dialog)
|
||||
.SetTitle("musikbox")
|
||||
.SetMessage("no output plugins found!")
|
||||
.AddButton(
|
||||
"KEY_ENTER",
|
||||
"ENTER",
|
||||
"ok");
|
||||
|
||||
App::Overlays().Push(dialog);
|
||||
}
|
||||
|
||||
OutputOverlay::OutputOverlay() {
|
||||
}
|
||||
|
||||
void OutputOverlay::Show(std::function<void()> callback) {
|
||||
plugins = outputs::GetAllOutputs();
|
||||
|
||||
if (!plugins.size()) {
|
||||
showNoOutputPluginsMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
using Adapter = cursespp::SimpleScrollAdapter;
|
||||
using ListOverlay = cursespp::ListOverlay;
|
||||
|
||||
std::shared_ptr<Adapter> adapter(new Adapter());
|
||||
|
||||
for (size_t i = 0; i < plugins.size(); i++) {
|
||||
adapter->AddEntry(plugins[i]->Name());
|
||||
}
|
||||
|
||||
adapter->SetSelectable(true);
|
||||
|
||||
std::shared_ptr<ListOverlay> dialog(new ListOverlay());
|
||||
|
||||
dialog->SetAdapter(adapter)
|
||||
.SetTitle("output plugins")
|
||||
.SetItemSelectedCallback(
|
||||
[callback](cursespp::IScrollAdapterPtr adapter, size_t index) {
|
||||
outputs::SelectOutput(plugins[index]);
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
|
||||
cursespp::App::Overlays().Push(dialog);
|
||||
}
|
49
src/musikbox/app/overlay/OutputOverlay.h
Normal file
49
src/musikbox/app/overlay/OutputOverlay.h
Normal file
@ -0,0 +1,49 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <functional>
|
||||
|
||||
namespace musik {
|
||||
namespace box {
|
||||
class OutputOverlay {
|
||||
public:
|
||||
static void Show(std::function<void()> callback);
|
||||
|
||||
private:
|
||||
OutputOverlay();
|
||||
};
|
||||
}
|
||||
}
|
@ -44,21 +44,6 @@
|
||||
|
||||
using namespace cursespp;
|
||||
|
||||
inline static void redrawContents(
|
||||
IWindow &window,
|
||||
const text::TextAlign alignment,
|
||||
const std::string& text)
|
||||
{
|
||||
std::string aligned = text::Align(
|
||||
text, alignment, window.GetContentWidth());
|
||||
|
||||
WINDOW* c = window.GetContent();
|
||||
werase(c);
|
||||
wprintw(c, aligned.c_str());
|
||||
|
||||
window.Repaint();
|
||||
}
|
||||
|
||||
TextLabel::TextLabel()
|
||||
: Window()
|
||||
, alignment(text::AlignLeft) {
|
||||
@ -68,15 +53,54 @@ TextLabel::TextLabel()
|
||||
TextLabel::~TextLabel() {
|
||||
}
|
||||
|
||||
void TextLabel::Redraw()
|
||||
{
|
||||
std::string aligned = text::Align(
|
||||
this->buffer, alignment, this->GetContentWidth());
|
||||
|
||||
WINDOW* c = this->GetContent();
|
||||
werase(c);
|
||||
|
||||
int64 attrs = this->IsFocused() ? CURSESPP_TEXT_FOCUSED : -1LL;
|
||||
|
||||
if (attrs != -1) {
|
||||
wattron(c, COLOR_PAIR(attrs));
|
||||
}
|
||||
|
||||
wprintw(c, aligned.c_str());
|
||||
|
||||
if (attrs != -1) {
|
||||
wattroff(c, COLOR_PAIR(attrs));
|
||||
}
|
||||
|
||||
this->Repaint();
|
||||
}
|
||||
|
||||
|
||||
void TextLabel::Show() {
|
||||
Window::Show();
|
||||
redrawContents(*this, this->alignment, this->buffer);
|
||||
this->Redraw();
|
||||
}
|
||||
|
||||
void TextLabel::OnFocusChanged(bool focused) {
|
||||
this->Redraw();
|
||||
}
|
||||
|
||||
void TextLabel::SetText(const std::string& value, const text::TextAlign alignment) {
|
||||
if (value != this->buffer || alignment != this->alignment) {
|
||||
this->buffer = value;
|
||||
this->alignment = alignment;
|
||||
redrawContents(*this, alignment, buffer);
|
||||
this->Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
bool TextLabel::KeyPress(const std::string& key) {
|
||||
if (this->IsFocused()) {
|
||||
if (key == " " || key == "KEY_ENTER") {
|
||||
this->Activated(this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -37,6 +37,7 @@
|
||||
#include <cursespp/curses_config.h>
|
||||
#include <cursespp/Window.h>
|
||||
#include <cursespp/IInput.h>
|
||||
#include <cursespp/IKeyHandler.h>
|
||||
#include <cursespp/Text.h>
|
||||
#include <sigslot/sigslot.h>
|
||||
|
||||
@ -44,11 +45,15 @@ namespace cursespp {
|
||||
class TextLabel :
|
||||
#if (__clang_major__ == 7 && __clang_minor__ == 3)
|
||||
public cursespp::Window,
|
||||
public cursespp::IKeyHandler,
|
||||
public std::enable_shared_from_this<TextLabel> {
|
||||
#else
|
||||
public cursespp::Window {
|
||||
public cursespp::Window,
|
||||
public cursespp::IKeyHandler {
|
||||
#endif
|
||||
public:
|
||||
sigslot::signal1<TextLabel*> Activated;
|
||||
|
||||
TextLabel();
|
||||
virtual ~TextLabel();
|
||||
|
||||
@ -61,7 +66,14 @@ namespace cursespp {
|
||||
|
||||
virtual void Show();
|
||||
|
||||
virtual bool KeyPress(const std::string& key);
|
||||
|
||||
protected:
|
||||
virtual void OnFocusChanged(bool focused);
|
||||
|
||||
private:
|
||||
void Redraw();
|
||||
|
||||
std::string buffer;
|
||||
text::TextAlign alignment;
|
||||
};
|
||||
|
@ -129,6 +129,7 @@
|
||||
<ClCompile Include="app\layout\TrackSearchLayout.cpp" />
|
||||
<ClCompile Include="app\model\DirectoryAdapter.cpp" />
|
||||
<ClCompile Include="app\model\TrackList.cpp" />
|
||||
<ClCompile Include="app\overlay\OutputOverlay.cpp" />
|
||||
<ClCompile Include="app\overlay\VisualizerOverlay.cpp" />
|
||||
<ClCompile Include="app\query\CategoryListViewQuery.cpp" />
|
||||
<ClCompile Include="app\query\NowPlayingTrackListQuery.cpp" />
|
||||
@ -185,6 +186,7 @@
|
||||
<ClInclude Include="app\layout\TrackSearchLayout.h" />
|
||||
<ClInclude Include="app\model\DirectoryAdapter.h" />
|
||||
<ClInclude Include="app\model\TrackList.h" />
|
||||
<ClInclude Include="app\overlay\OutputOverlay.h" />
|
||||
<ClInclude Include="app\overlay\VisualizerOverlay.h" />
|
||||
<ClInclude Include="app\query\CategoryListViewQuery.h" />
|
||||
<ClInclude Include="app\query\NowPlayingTrackListQuery.h" />
|
||||
|
@ -147,6 +147,9 @@
|
||||
<ClCompile Include="app\overlay\VisualizerOverlay.cpp">
|
||||
<Filter>app\overlay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="app\overlay\OutputOverlay.cpp">
|
||||
<Filter>app\overlay</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
@ -345,6 +348,9 @@
|
||||
<ClInclude Include="app\overlay\VisualizerOverlay.h">
|
||||
<Filter>app\overlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="app\overlay\OutputOverlay.h">
|
||||
<Filter>app\overlay</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="cursespp">
|
||||
|
Loading…
x
Reference in New Issue
Block a user