mirror of
https://github.com/clangen/musikcube.git
synced 2025-03-14 13:21:13 +00:00
Merge branch 'clangen/tracklist_headers'
This commit is contained in:
commit
0a57ccce25
@ -673,7 +673,7 @@ class PlaybackRemote : public IPlaybackRemote {
|
||||
{ key::title, album->GetDescription() },
|
||||
{ key::id, album->GetId() },
|
||||
{ key::thumbnail_id, 0 }, /* note: thumbnails aren't supported at the album level yet */
|
||||
{ key::album_artist_id, this->GetMetadataInt64(album, key::album_artist_id) },
|
||||
{ key::album_artist_id, album->GetInt64(key::album_artist_id.c_str()) },
|
||||
{ key::album_artist, this->GetMetadataString(album, key::album_artist) }
|
||||
});
|
||||
|
||||
@ -852,14 +852,14 @@ class PlaybackRemote : public IPlaybackRemote {
|
||||
{ key::id, track->GetId() },
|
||||
{ key::title, this->GetMetadataString(track, key::title) },
|
||||
{ key::album, this->GetMetadataString(track, key::album) },
|
||||
{ key::album_id, this->GetMetadataInt64(track, key::album_id) },
|
||||
{ key::album_id, track->GetInt64(key::album_id.c_str()) },
|
||||
{ key::album_artist, this->GetMetadataString(track, key::album_artist) },
|
||||
{ key::album_artist_id, this->GetMetadataInt64(track, key::album_artist_id) },
|
||||
{ key::album_artist_id, track->GetInt64(key::album_artist_id.c_str()) },
|
||||
{ key::artist, this->GetMetadataString(track, key::artist) },
|
||||
{ key::artist_id, this->GetMetadataInt64(track, key::artist_id) },
|
||||
{ key::artist_id, track->GetInt64(key::artist_id.c_str()) },
|
||||
{ key::genre, this->GetMetadataString(track, key::genre) },
|
||||
{ key::genre_id, this->GetMetadataInt64(track, key::genre_id) },
|
||||
{ key::thumbnail_id, this->GetMetadataInt64(track, key::thumbnail_id) },
|
||||
{ key::genre_id, track->GetInt64(key::genre_id.c_str()) },
|
||||
{ key::thumbnail_id, track->GetInt64(key::thumbnail_id.c_str()) },
|
||||
};
|
||||
}
|
||||
|
||||
@ -896,16 +896,6 @@ class PlaybackRemote : public IPlaybackRemote {
|
||||
return std::string(threadLocalBuffer);
|
||||
}
|
||||
|
||||
template <typename MetadataT>
|
||||
unsigned long long GetMetadataInt64(MetadataT* metadata, const std::string& idKey) {
|
||||
try {
|
||||
return std::stoull(this->GetMetadataString(metadata, idKey));
|
||||
}
|
||||
catch (...) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadProc() {
|
||||
try {
|
||||
if (preferences->GetBool("debug")) {
|
||||
|
@ -41,14 +41,16 @@
|
||||
#include "Locale.h"
|
||||
|
||||
#define KEY_STRINGS "strings"
|
||||
#define KEY_DIMENSIONS "dimensions"
|
||||
#define DEFAULT_LOCALE "en_US"
|
||||
|
||||
using namespace musik::core::i18n;
|
||||
using namespace musik::core;
|
||||
using namespace musik::core::prefs;
|
||||
|
||||
using namespace boost::filesystem;
|
||||
|
||||
static nlohmann::json empty;
|
||||
|
||||
static nlohmann::json loadLocaleData(const std::string& fn) {
|
||||
char* bytes = nullptr;
|
||||
int count = 0;
|
||||
@ -142,13 +144,10 @@ std::string Locale::Translate(const std::string& key) {
|
||||
}
|
||||
|
||||
std::string Locale::Translate(const char* key) {
|
||||
static nlohmann::json empty;
|
||||
|
||||
/* get the string from the current locale */
|
||||
if (!this->localeData.is_null()) {
|
||||
const nlohmann::json& strings = this->localeData.value(KEY_STRINGS, empty);
|
||||
auto it = strings.find(key);
|
||||
|
||||
if (it != strings.end()) {
|
||||
return it.value();
|
||||
}
|
||||
@ -163,4 +162,22 @@ std::string Locale::Translate(const char* key) {
|
||||
|
||||
/* otherwise, just return the key! */
|
||||
return key;
|
||||
}
|
||||
|
||||
int Locale::Dimension(const char* key, int defaultValue) {
|
||||
if (!this->localeData.is_null()) { /* current locale */
|
||||
const nlohmann::json& strings = this->localeData.value(KEY_DIMENSIONS, empty);
|
||||
auto it = strings.find(key);
|
||||
if (it != strings.end()) {
|
||||
return it.value();
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->defaultLocaleData.is_null()) { /* fall back to default */
|
||||
const nlohmann::json& strings = this->defaultLocaleData.value(KEY_DIMENSIONS, empty);
|
||||
auto it = strings.find(key);
|
||||
return (it != strings.end()) ? it.value() : key;
|
||||
}
|
||||
|
||||
return defaultValue; /* not found anywhere */
|
||||
}
|
@ -62,6 +62,8 @@ namespace musik { namespace core { namespace i18n {
|
||||
std::string Translate(const std::string& key);
|
||||
std::string Translate(const char* key);
|
||||
|
||||
int Dimension(const char* key, int defaultValue);
|
||||
|
||||
private:
|
||||
Locale();
|
||||
|
||||
@ -75,6 +77,7 @@ namespace musik { namespace core { namespace i18n {
|
||||
|
||||
#define _TSTR(KEY) (musik::core::i18n::Locale::Instance().Translate(KEY))
|
||||
#define _TCP(KEY) (musik::core::i18n::Locale::Instance().Translate(KEY).c_str())
|
||||
#define _DIMEN(KEY, DEFAULT) (musik::core::i18n::Locale::Instance().Dimension(KEY, DEFAULT))
|
||||
|
||||
} } }
|
||||
|
||||
|
@ -57,6 +57,11 @@ namespace {
|
||||
virtual void Release() { this->wrapped.reset(); }
|
||||
virtual unsigned long long GetId() { return this->wrapped->GetId(); }
|
||||
virtual int GetValue(const char* key, char* dst, int size) { return this->wrapped->GetValue(key, dst, size); }
|
||||
virtual unsigned long long GetUint64(const char* key, unsigned long long defaultValue) { return this->wrapped->GetUint64(key, defaultValue); }
|
||||
virtual long long GetInt64(const char* key, long long defaultValue) { return this->wrapped->GetInt64(key, defaultValue); }
|
||||
virtual unsigned long GetUint32(const char* key, unsigned long defaultValue) { return this->wrapped->GetUint32(key, defaultValue); }
|
||||
virtual long GetInt32(const char* key, unsigned int defaultValue) { return this->wrapped->GetInt32(key, defaultValue); }
|
||||
virtual double GetDouble(const char* key, double defaultValue) { return this->wrapped->GetDouble(key, defaultValue); }
|
||||
virtual const char* GetDescription() { return this->wrapped->GetDescription(); }
|
||||
virtual const char* GetType() { return this->wrapped->GetType(); }
|
||||
MetadataMapPtr wrapped;
|
||||
@ -98,6 +103,39 @@ int MetadataMap::GetValue(const char* key, char* dst, int size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string MetadataMap::GetValue(const char* key) {
|
||||
auto it = metadata.find(key);
|
||||
if (it != metadata.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
unsigned long long MetadataMap::GetUint64(const char* key, unsigned long long defaultValue) {
|
||||
try { return std::stoull(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
long long MetadataMap::GetInt64(const char* key, long long defaultValue) {
|
||||
try { return std::stoll(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
unsigned long MetadataMap::GetUint32(const char* key, unsigned long defaultValue) {
|
||||
try { return std::stoul(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
long MetadataMap::GetInt32(const char* key, unsigned int defaultValue) {
|
||||
try { return std::stol(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
double MetadataMap::GetDouble(const char* key, double defaultValue) {
|
||||
try { return std::stod(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
const char* MetadataMap::GetDescription() {
|
||||
return this->description.c_str();
|
||||
}
|
||||
|
@ -56,12 +56,19 @@ namespace musik { namespace core {
|
||||
/* IMetadataMap */
|
||||
virtual void Release();
|
||||
virtual unsigned long long GetId();
|
||||
virtual int GetValue(const char* key, char* dst, int size);
|
||||
virtual const char* GetDescription();
|
||||
virtual const char* GetType();
|
||||
|
||||
virtual int GetValue(const char* key, char* dst, int size);
|
||||
virtual unsigned long long GetUint64(const char* key, unsigned long long defaultValue = 0ULL);
|
||||
virtual long long GetInt64(const char* key, long long defaultValue = 0LL);
|
||||
virtual unsigned long GetUint32(const char* key, unsigned long defaultValue = 0);
|
||||
virtual long GetInt32(const char* key, unsigned int defaultValue = 0);
|
||||
virtual double GetDouble(const char* key, double defaultValue = 0.0f);
|
||||
|
||||
/* implementation specific */
|
||||
void SetValue(const char* key, const std::string& value);
|
||||
std::string GetValue(const char* key);
|
||||
musik::core::sdk::IMetadataMap* GetSdkValue();
|
||||
|
||||
private:
|
||||
|
@ -87,6 +87,31 @@ std::string IndexerTrack::GetValue(const char* metakey) {
|
||||
return "";
|
||||
}
|
||||
|
||||
unsigned long long IndexerTrack::GetUint64(const char* key, unsigned long long defaultValue) {
|
||||
try { return std::stoull(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
long long IndexerTrack::GetInt64(const char* key, long long defaultValue) {
|
||||
try { return std::stoll(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
unsigned long IndexerTrack::GetUint32(const char* key, unsigned long defaultValue) {
|
||||
try { return std::stoul(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
long IndexerTrack::GetInt32(const char* key, unsigned int defaultValue) {
|
||||
try { return std::stol(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
double IndexerTrack::GetDouble(const char* key, double defaultValue) {
|
||||
try { return std::stod(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
void IndexerTrack::SetValue(const char* metakey, const char* value) {
|
||||
if (metakey && value) {
|
||||
this->internalMetadata->metadata.insert(
|
||||
|
@ -51,6 +51,11 @@ namespace musik { namespace core {
|
||||
|
||||
virtual std::string GetValue(const char* metakey);
|
||||
virtual int GetValue(const char* key, char* dst, int size);
|
||||
virtual unsigned long long GetUint64(const char* key, unsigned long long defaultValue = 0ULL);
|
||||
virtual long long GetInt64(const char* key, long long defaultValue = 0LL);
|
||||
virtual unsigned long GetUint32(const char* key, unsigned long defaultValue = 0);
|
||||
virtual long GetInt32(const char* key, unsigned int defaultValue = 0);
|
||||
virtual double GetDouble(const char* key, double defaultValue = 0.0f);
|
||||
|
||||
virtual std::string Uri();
|
||||
virtual int Uri(char* dst, int size);
|
||||
|
@ -71,6 +71,31 @@ std::string LibraryTrack::GetValue(const char* metakey) {
|
||||
return "";
|
||||
}
|
||||
|
||||
unsigned long long LibraryTrack::GetUint64(const char* key, unsigned long long defaultValue) {
|
||||
try { return std::stoull(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
long long LibraryTrack::GetInt64(const char* key, long long defaultValue) {
|
||||
try { return std::stoll(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
unsigned long LibraryTrack::GetUint32(const char* key, unsigned long defaultValue) {
|
||||
try { return std::stoul(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
long LibraryTrack::GetInt32(const char* key, unsigned int defaultValue) {
|
||||
try { return std::stol(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
double LibraryTrack::GetDouble(const char* key, double defaultValue) {
|
||||
try { return std::stod(GetValue(key)); } catch (...) { }
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
void LibraryTrack::SetValue(const char* metakey, const char* value) {
|
||||
std::unique_lock<std::mutex> lock(this->data.mutex);
|
||||
this->data.metadata.insert(std::pair<std::string, std::string>(metakey,value));
|
||||
|
@ -59,6 +59,12 @@ namespace musik { namespace core {
|
||||
virtual void SetThumbnail(const char *data, long size);
|
||||
|
||||
virtual std::string GetValue(const char* metakey);
|
||||
virtual unsigned long long GetUint64(const char* key, unsigned long long defaultValue = 0ULL);
|
||||
virtual long long GetInt64(const char* key, long long defaultValue = 0LL);
|
||||
virtual unsigned long GetUint32(const char* key, unsigned long defaultValue = 0);
|
||||
virtual long GetInt32(const char* key, unsigned int defaultValue = 0);
|
||||
virtual double GetDouble(const char* key, double defaultValue = 0.0f);
|
||||
|
||||
virtual std::string Uri();
|
||||
|
||||
virtual int GetValue(const char* key, char* dst, int size);
|
||||
|
@ -61,6 +61,26 @@ int RetainedTrack::Uri(char* dst, int size) {
|
||||
return track->Uri(dst, size);
|
||||
}
|
||||
|
||||
unsigned long long RetainedTrack::GetUint64(const char* key, unsigned long long defaultValue) {
|
||||
return track->GetUint64(key, defaultValue);
|
||||
}
|
||||
|
||||
long long RetainedTrack::GetInt64(const char* key, long long defaultValue) {
|
||||
return track->GetInt64(key, defaultValue);
|
||||
}
|
||||
|
||||
unsigned long RetainedTrack::GetUint32(const char* key, unsigned long defaultValue) {
|
||||
return track->GetUint32(key, defaultValue);
|
||||
}
|
||||
|
||||
long RetainedTrack::GetInt32(const char* key, unsigned int defaultValue) {
|
||||
return track->GetInt32(key, defaultValue);
|
||||
}
|
||||
|
||||
double RetainedTrack::GetDouble(const char* key, double defaultValue) {
|
||||
return track->GetDouble(key, defaultValue);
|
||||
}
|
||||
|
||||
unsigned long long RetainedTrack::GetId() {
|
||||
return track->GetId();
|
||||
}
|
||||
|
@ -45,7 +45,14 @@ namespace musik { namespace core {
|
||||
|
||||
virtual unsigned long long GetId();
|
||||
virtual void Release();
|
||||
|
||||
virtual int GetValue(const char* key, char* dst, int size);
|
||||
virtual unsigned long long GetUint64(const char* key, unsigned long long defaultValue = 0ULL);
|
||||
virtual long long GetInt64(const char* key, long long defaultValue = 0LL);
|
||||
virtual unsigned long GetUint32(const char* key, unsigned long defaultValue = 0);
|
||||
virtual long GetInt32(const char* key, unsigned int defaultValue = 0);
|
||||
virtual double GetDouble(const char* key, double defaultValue = 0.0f);
|
||||
|
||||
virtual int Uri(char* dst, int size);
|
||||
|
||||
private:
|
||||
|
@ -67,6 +67,12 @@ namespace musik { namespace core {
|
||||
virtual std::string Uri() = 0;
|
||||
|
||||
virtual int GetValue(const char* key, char* dst, int size) = 0;
|
||||
virtual unsigned long long GetUint64(const char* key, unsigned long long defaultValue = 0ULL) = 0;
|
||||
virtual long long GetInt64(const char* key, long long defaultValue = 0LL) = 0;
|
||||
virtual unsigned long GetUint32(const char* key, unsigned long defaultValue = 0) = 0;
|
||||
virtual long GetInt32(const char* key, unsigned int defaultValue = 0) = 0;
|
||||
virtual double GetDouble(const char* key, double defaultValue = 0.0f) = 0;
|
||||
|
||||
virtual int Uri(char* dst, int size) = 0;
|
||||
|
||||
virtual MetadataIteratorRange GetValues(const char* metakey) = 0;
|
||||
|
@ -45,8 +45,11 @@ namespace musik {
|
||||
virtual ~IMessageQueue() { }
|
||||
virtual void Post(IMessagePtr message, int64 delayMs = 0) = 0;
|
||||
virtual int Remove(IMessageTarget *target, int type = -1) = 0;
|
||||
virtual void Broadcast(IMessagePtr message, int64 delayMs = 0) = 0;
|
||||
virtual bool Contains(IMessageTarget *target, int type = -1) = 0;
|
||||
virtual void Debounce(IMessagePtr message, int64 delayMs = 0) = 0;
|
||||
virtual void RegisterForBroadcasts(IMessageTargetPtr target) = 0;
|
||||
virtual void UnregisterForBroadcasts(IMessageTargetPtr target) = 0;
|
||||
virtual void WaitAndDispatch() = 0;
|
||||
virtual void Dispatch() = 0;
|
||||
};
|
||||
|
@ -37,9 +37,13 @@
|
||||
#include "IMessage.h"
|
||||
|
||||
namespace musik { namespace core { namespace runtime {
|
||||
|
||||
class IMessageTarget {
|
||||
public:
|
||||
virtual ~IMessageTarget() { }
|
||||
virtual void ProcessMessage(IMessage &message) = 0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<IMessageTarget> IMessageTargetPtr;
|
||||
|
||||
} } }
|
||||
|
@ -49,8 +49,8 @@ namespace musik { namespace core { namespace runtime {
|
||||
static IMessagePtr Create(
|
||||
IMessageTarget* target,
|
||||
int messageType,
|
||||
int64 data1,
|
||||
int64 data2);
|
||||
int64 data1 = 0LL,
|
||||
int64 data2 = 0LL);
|
||||
|
||||
virtual ~Message() {
|
||||
}
|
||||
|
@ -124,6 +124,19 @@ void MessageQueue::Dispatch() {
|
||||
}
|
||||
}
|
||||
|
||||
void MessageQueue::RegisterForBroadcasts(IMessageTargetPtr target) {
|
||||
LockT lock(this->queueMutex);
|
||||
this->receivers.insert(target);
|
||||
}
|
||||
|
||||
void MessageQueue::UnregisterForBroadcasts(IMessageTargetPtr target) {
|
||||
LockT lock(this->queueMutex);
|
||||
auto it = this->receivers.find(target);
|
||||
if (it != this->receivers.end()) {
|
||||
this->receivers.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
int MessageQueue::Remove(IMessageTarget *target, int type) {
|
||||
LockT lock(this->queueMutex);
|
||||
|
||||
@ -169,6 +182,14 @@ bool MessageQueue::Contains(IMessageTarget *target, int type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void MessageQueue::Broadcast(IMessagePtr message, int64 delayMs) {
|
||||
if (message->Target()) {
|
||||
throw new std::runtime_error("broadcasts cannot have a target!");
|
||||
}
|
||||
|
||||
this->Post(message, delayMs);
|
||||
}
|
||||
|
||||
void MessageQueue::Post(IMessagePtr message, int64 delayMs) {
|
||||
LockT lock(this->queueMutex);
|
||||
|
||||
@ -215,5 +236,23 @@ void MessageQueue::Debounce(IMessagePtr message, int64 delayMs) {
|
||||
}
|
||||
|
||||
void MessageQueue::Dispatch(IMessagePtr message) {
|
||||
message->Target()->ProcessMessage(*message);
|
||||
if (message->Target()) {
|
||||
message->Target()->ProcessMessage(*message);
|
||||
}
|
||||
else {
|
||||
std::set<IMessageTargetPtr> copy;
|
||||
|
||||
{
|
||||
LockT lock(this->queueMutex);
|
||||
|
||||
std::copy(
|
||||
receivers.begin(),
|
||||
receivers.end(),
|
||||
std::inserter(copy, copy.begin()));
|
||||
}
|
||||
|
||||
for (auto receiver : copy) {
|
||||
receiver->ProcessMessage(*message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <condition_variable>
|
||||
#include <chrono>
|
||||
#include <atomic>
|
||||
#include <set>
|
||||
|
||||
namespace musik { namespace core { namespace runtime {
|
||||
class MessageQueue : public IMessageQueue {
|
||||
@ -49,9 +50,12 @@ namespace musik { namespace core { namespace runtime {
|
||||
virtual ~MessageQueue();
|
||||
|
||||
virtual void Post(IMessagePtr message, int64 delayMs = 0);
|
||||
virtual void Broadcast(IMessagePtr message, int64 messageMs = 0);
|
||||
virtual int Remove(IMessageTarget *target, int type = -1);
|
||||
virtual bool Contains(IMessageTarget *target, int type = -1);
|
||||
virtual void Debounce(IMessagePtr message, int64 delayMs = 0);
|
||||
virtual void RegisterForBroadcasts(IMessageTargetPtr target);
|
||||
virtual void UnregisterForBroadcasts(IMessageTargetPtr target);
|
||||
virtual void WaitAndDispatch();
|
||||
virtual void Dispatch();
|
||||
|
||||
@ -69,6 +73,7 @@ namespace musik { namespace core { namespace runtime {
|
||||
std::mutex queueMutex;
|
||||
std::list<EnqueuedMessage*> queue;
|
||||
std::list<EnqueuedMessage*> dispatch;
|
||||
std::set<IMessageTargetPtr> receivers;
|
||||
std::condition_variable_any waitForDispatch;
|
||||
std::atomic<int64> nextMessageTime;
|
||||
|
||||
|
@ -41,6 +41,11 @@ namespace musik { namespace core { namespace sdk {
|
||||
virtual void Release() = 0;
|
||||
virtual unsigned long long GetId() = 0;
|
||||
virtual int GetValue(const char* key, char* dst, int size) = 0;
|
||||
virtual unsigned long long GetUint64(const char* key, unsigned long long defaultValue = 0ULL) = 0;
|
||||
virtual long long GetInt64(const char* key, long long defaultValue = 0LL) = 0;
|
||||
virtual unsigned long GetUint32(const char* key, unsigned long defaultValue = 0) = 0;
|
||||
virtual long GetInt32(const char* key, unsigned int defaultValue = 0) = 0;
|
||||
virtual double GetDouble(const char* key, double defaultValue = 0.0f) = 0;
|
||||
virtual const char* GetDescription() = 0;
|
||||
virtual const char* GetType() = 0;
|
||||
};
|
||||
|
@ -40,6 +40,11 @@ namespace musik { namespace core { namespace sdk {
|
||||
public:
|
||||
virtual unsigned long long GetId() = 0;
|
||||
virtual int GetValue(const char* key, char* dst, int size) = 0;
|
||||
virtual unsigned long long GetUint64(const char* key, unsigned long long defaultValue = 0ULL) = 0;
|
||||
virtual long long GetInt64(const char* key, long long defaultValue = 0LL) = 0;
|
||||
virtual unsigned long GetUint32(const char* key, unsigned long defaultValue = 0) = 0;
|
||||
virtual long GetInt32(const char* key, unsigned int defaultValue = 0) = 0;
|
||||
virtual double GetDouble(const char* key, double defaultValue = 0.0f) = 0;
|
||||
virtual int Uri(char* dst, int size) = 0;
|
||||
};
|
||||
|
||||
|
@ -108,5 +108,5 @@ namespace musik {
|
||||
static const char* AlbumId = "album_id";
|
||||
}
|
||||
|
||||
static const int SdkVersion = 3;
|
||||
static const int SdkVersion = 4;
|
||||
} } }
|
@ -21,7 +21,6 @@ set (BOX_SRCS
|
||||
./app/util/PreferenceKeys.cpp
|
||||
./app/util/Playback.cpp
|
||||
./app/window/CategoryListView.cpp
|
||||
./app/window/EntryWithHeader.cpp
|
||||
./app/window/LogWindow.cpp
|
||||
./app/window/TrackListView.cpp
|
||||
./app/window/TransportWindow.cpp
|
||||
|
@ -56,6 +56,8 @@ using namespace cursespp;
|
||||
static size_t MAX_CATEGORY_WIDTH = 40;
|
||||
static int MIN_LIST_TITLE_HEIGHT = 26;
|
||||
|
||||
#define MESSAGE_INDEXER_PROGRESS 2033
|
||||
|
||||
#define DEFAULT_CATEGORY constants::Track::ARTIST
|
||||
#define DEFAULT_CATEGORY_NAME FIELD_TO_TITLE[DEFAULT_CATEGORY]
|
||||
|
||||
@ -137,6 +139,14 @@ void BrowseLayout::InitializeWindows() {
|
||||
this, &BrowseLayout::OnCategoryViewInvalidated);
|
||||
}
|
||||
|
||||
void BrowseLayout::ProcessMessage(musik::core::runtime::IMessage &message) {
|
||||
if (message.Type() == MESSAGE_INDEXER_PROGRESS) {
|
||||
this->categoryList->Requery();
|
||||
}
|
||||
|
||||
LayoutBase::ProcessMessage(message);
|
||||
}
|
||||
|
||||
void BrowseLayout::ScrollTo(const std::string& fieldType, DBID fieldId) {
|
||||
this->SetFocus(this->trackList);
|
||||
this->categoryList->RequeryWithField(fieldType, "", fieldId);
|
||||
@ -153,12 +163,13 @@ void BrowseLayout::OnVisibilityChanged(bool visible) {
|
||||
LayoutBase::OnVisibilityChanged(visible);
|
||||
|
||||
if (visible) {
|
||||
Window::MessageQueue().RegisterForBroadcasts(shared_from_this());
|
||||
this->categoryList->Requery();
|
||||
}
|
||||
}
|
||||
|
||||
void BrowseLayout::OnIndexerProgress(int count) {
|
||||
this->categoryList->Requery();
|
||||
this->PostMessage(MESSAGE_INDEXER_PROGRESS);
|
||||
}
|
||||
|
||||
void BrowseLayout::RequeryTrackList(ListWindow *view) {
|
||||
@ -201,8 +212,11 @@ bool BrowseLayout::KeyPress(const std::string& key) {
|
||||
}
|
||||
else if (Hotkeys::Is(Hotkeys::ContextMenu, key)) {
|
||||
if (this->GetFocus() == this->trackList) {
|
||||
PlayQueueOverlays::ShowAddTrackOverlay(this->playback, *this->trackList);
|
||||
return true;
|
||||
TrackPtr track = this->trackList->GetSelectedTrack();
|
||||
if (track) {
|
||||
PlayQueueOverlays::ShowAddTrackOverlay(this->playback, track->GetId());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Hotkeys::Is(Hotkeys::ViewRefresh, key)) {
|
||||
|
@ -65,7 +65,7 @@ namespace musik {
|
||||
virtual void OnVisibilityChanged(bool visible);
|
||||
virtual cursespp::IWindowPtr GetFocus();
|
||||
virtual bool KeyPress(const std::string& key);
|
||||
|
||||
virtual void ProcessMessage(musik::core::runtime::IMessage &message);
|
||||
void ScrollTo(const std::string& fieldType, DBID fieldId);
|
||||
|
||||
protected:
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include <core/library/LocalLibraryConstants.h>
|
||||
|
||||
#include <app/overlay/PlayQueueOverlays.h>
|
||||
#include <app/util/Hotkeys.h>
|
||||
#include <glue/util/Playback.h>
|
||||
|
||||
@ -146,6 +147,7 @@ void LibraryLayout::ShowTrackSearch() {
|
||||
|
||||
void LibraryLayout::InitializeWindows() {
|
||||
this->browseLayout.reset(new BrowseLayout(this->playback, this->library));
|
||||
|
||||
this->nowPlayingLayout.reset(new NowPlayingLayout(this->playback, this->library));
|
||||
|
||||
this->searchLayout.reset(new SearchLayout(this->playback, this->library));
|
||||
@ -194,6 +196,14 @@ void LibraryLayout::UpdateShortcutsWindow() {
|
||||
}
|
||||
}
|
||||
|
||||
void LibraryLayout::OnAddedToParent(IWindow* parent) {
|
||||
MessageQueue().RegisterForBroadcasts(shared_from_this());
|
||||
}
|
||||
|
||||
void LibraryLayout::OnRemovedFromParent(IWindow* parent) {
|
||||
MessageQueue().UnregisterForBroadcasts(shared_from_this());
|
||||
}
|
||||
|
||||
void LibraryLayout::OnSearchResultSelected(
|
||||
SearchLayout* layout, std::string fieldType, DBID fieldId)
|
||||
{
|
||||
@ -255,6 +265,14 @@ bool LibraryLayout::SetFocus(cursespp::IWindowPtr window) {
|
||||
return this->visibleLayout->SetFocus(window);
|
||||
}
|
||||
|
||||
void LibraryLayout::ProcessMessage(musik::core::runtime::IMessage &message) {
|
||||
if (message.Type() == PlayQueueOverlays::BROADCAST_JUMP_TO_ALBUM) {
|
||||
this->OnSearchResultSelected(nullptr, constants::Track::ALBUM, message.UserData1());
|
||||
}
|
||||
|
||||
LayoutBase::ProcessMessage(message);
|
||||
}
|
||||
|
||||
bool LibraryLayout::KeyPress(const std::string& key) {
|
||||
if (key == "^[") { /* switches between browse/now playing */
|
||||
if (this->visibleLayout != this->browseLayout) {
|
||||
|
@ -68,6 +68,7 @@ namespace musik {
|
||||
virtual cursespp::IWindowPtr FocusPrev();
|
||||
virtual cursespp::IWindowPtr GetFocus();
|
||||
virtual bool SetFocus(cursespp::IWindowPtr window);
|
||||
virtual void ProcessMessage(musik::core::runtime::IMessage &message);
|
||||
|
||||
virtual void SetShortcutsWindow(
|
||||
cursespp::ShortcutsWindow* w);
|
||||
@ -76,6 +77,8 @@ namespace musik {
|
||||
|
||||
protected:
|
||||
virtual void OnLayout();
|
||||
virtual void OnAddedToParent(IWindow* newParent);
|
||||
virtual void OnRemovedFromParent(IWindow* oldParent);
|
||||
|
||||
private:
|
||||
void OnSearchResultSelected(
|
||||
|
@ -152,7 +152,10 @@ bool TrackSearchLayout::KeyPress(const std::string& key) {
|
||||
return true;
|
||||
}
|
||||
else if (Hotkeys::Is(Hotkeys::ContextMenu, key)) {
|
||||
PlayQueueOverlays::ShowAddTrackOverlay(this->playback, *this->trackList);
|
||||
TrackPtr track = this->trackList->GetSelectedTrack();
|
||||
if (track) {
|
||||
PlayQueueOverlays::ShowAddTrackOverlay(this->playback, track->GetId());
|
||||
}
|
||||
}
|
||||
else if (key == "KEY_DOWN") {
|
||||
if (this->GetFocus() == this->input) {
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <core/library/query/local/GetPlaylistQuery.h>
|
||||
#include <core/library/query/local/SavePlaylistQuery.h>
|
||||
#include <core/library/query/local/DeletePlaylistQuery.h>
|
||||
#include <core/runtime/Message.h>
|
||||
|
||||
#include <cursespp/App.h>
|
||||
#include <cursespp/SimpleScrollAdapter.h>
|
||||
@ -114,7 +115,7 @@ static void showPlaylistListOverlay(
|
||||
|
||||
dialog->SetAdapter(adapter)
|
||||
.SetTitle(title)
|
||||
.SetWidth(DEFAULT_OVERLAY_WIDTH)
|
||||
.SetWidth(_DIMEN("playqueue_playlist_list_overlay", DEFAULT_OVERLAY_WIDTH))
|
||||
.SetSelectedIndex(selectedIndex)
|
||||
.SetItemSelectedCallback(callback);
|
||||
|
||||
@ -153,7 +154,7 @@ static void createNewPlaylist(
|
||||
std::shared_ptr<InputOverlay> dialog(new InputOverlay());
|
||||
|
||||
dialog->SetTitle(_TSTR("playqueue_overlay_playlist_name_title"))
|
||||
.SetWidth(DEFAULT_OVERLAY_WIDTH)
|
||||
.SetWidth(_DIMEN("playqueue_playlist_name_overlay", DEFAULT_OVERLAY_WIDTH))
|
||||
.SetText("")
|
||||
.SetInputAcceptedCallback(
|
||||
[tracks, library](const std::string& name) {
|
||||
@ -173,7 +174,7 @@ static void renamePlaylist(
|
||||
std::shared_ptr<InputOverlay> dialog(new InputOverlay());
|
||||
|
||||
dialog->SetTitle(_TSTR("playqueue_overlay_new_playlist_name_title"))
|
||||
.SetWidth(DEFAULT_OVERLAY_WIDTH)
|
||||
.SetWidth(_DIMEN("playqueue_playlist_name_overlay", DEFAULT_OVERLAY_WIDTH))
|
||||
.SetText(oldName)
|
||||
.SetInputAcceptedCallback(
|
||||
[library, playlistId](const std::string& name) {
|
||||
@ -221,29 +222,51 @@ static void showNoPlaylistsDialog() {
|
||||
App::Overlays().Push(dialog);
|
||||
}
|
||||
|
||||
static void handleAddCategorySelection(
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
musik::core::ILibraryPtr library,
|
||||
const std::string& fieldColumn,
|
||||
DBID fieldId,
|
||||
size_t type)
|
||||
{
|
||||
std::shared_ptr<CategoryTrackListQuery> query(
|
||||
new CategoryTrackListQuery(library, fieldColumn, fieldId));
|
||||
|
||||
library->Enqueue(query, ILibrary::QuerySynchronous);
|
||||
|
||||
if (query->GetStatus() == IQuery::Finished) {
|
||||
auto editor = playback.Edit();
|
||||
auto tracks = query->GetResult();
|
||||
size_t position = playback.GetIndex();
|
||||
|
||||
if (type == 0 || position == ListWindow::NO_SELECTION) { /* end */
|
||||
for (size_t i = 0; i < tracks->Count(); i++) {
|
||||
editor.Add(tracks->GetId(i));
|
||||
}
|
||||
}
|
||||
else { /* after next */
|
||||
for (size_t i = 0; i < tracks->Count(); i++) {
|
||||
editor.Insert(tracks->GetId(i), position + 1 + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlayQueueOverlays::PlayQueueOverlays() {
|
||||
}
|
||||
|
||||
void PlayQueueOverlays::ShowAddTrackOverlay(
|
||||
PlaybackService& playback,
|
||||
TrackListView& trackList)
|
||||
unsigned long long trackId)
|
||||
{
|
||||
size_t selectedIndex = trackList.GetSelectedIndex();
|
||||
|
||||
if (selectedIndex == ListWindow::NO_SELECTION) {
|
||||
return;
|
||||
}
|
||||
|
||||
DBID trackId = trackList.Get(selectedIndex)->GetId();
|
||||
|
||||
auto adapter = createAddToAdapter();
|
||||
|
||||
std::shared_ptr<ListOverlay> dialog(new ListOverlay());
|
||||
|
||||
dialog->SetAdapter(adapter)
|
||||
.SetTitle(_TSTR("playqueue_overlay_add_to_queue_title"))
|
||||
.SetWidth(_DIMEN("playqueue_playlist_add_to_queue_overlay", DEFAULT_OVERLAY_WIDTH))
|
||||
.SetSelectedIndex(0)
|
||||
.SetWidth(DEFAULT_OVERLAY_WIDTH)
|
||||
.SetItemSelectedCallback(
|
||||
[trackId, &playback](ListOverlay* overlay, IScrollAdapterPtr adapter, size_t index) {
|
||||
auto editor = playback.Edit();
|
||||
@ -276,8 +299,8 @@ void PlayQueueOverlays::ShowAddCategoryOverlay(
|
||||
|
||||
dialog->SetAdapter(adapter)
|
||||
.SetTitle(_TSTR("playqueue_overlay_add_to_queue_title"))
|
||||
.SetWidth(_DIMEN("playqueue_playlist_add_to_queue_overlay", DEFAULT_OVERLAY_WIDTH))
|
||||
.SetSelectedIndex(0)
|
||||
.SetWidth(DEFAULT_OVERLAY_WIDTH)
|
||||
.SetItemSelectedCallback(
|
||||
[&playback, library, fieldColumn, fieldId]
|
||||
(ListOverlay* overlay, IScrollAdapterPtr adapter, size_t index) {
|
||||
@ -285,35 +308,53 @@ void PlayQueueOverlays::ShowAddCategoryOverlay(
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<CategoryTrackListQuery>
|
||||
query(new CategoryTrackListQuery(
|
||||
library,
|
||||
fieldColumn,
|
||||
fieldId));
|
||||
|
||||
library->Enqueue(query, ILibrary::QuerySynchronous);
|
||||
|
||||
if (query->GetStatus() == IQuery::Finished) {
|
||||
auto editor = playback.Edit();
|
||||
auto tracks = query->GetResult();
|
||||
size_t position = playback.GetIndex();
|
||||
|
||||
if (index == 0 || position == ListWindow::NO_SELECTION) { /* end */
|
||||
for (size_t i = 0; i < tracks->Count(); i++) {
|
||||
editor.Add(tracks->GetId(i));
|
||||
}
|
||||
}
|
||||
else { /* after next */
|
||||
for (size_t i = 0; i < tracks->Count(); i++) {
|
||||
editor.Insert(tracks->GetId(i), position + 1 + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
handleAddCategorySelection(playback, library, fieldColumn, fieldId, index);
|
||||
});
|
||||
|
||||
cursespp::App::Overlays().Push(dialog);
|
||||
}
|
||||
|
||||
void PlayQueueOverlays::ShowAlbumDividerOverlay(
|
||||
musik::core::runtime::IMessageQueue& messageQueue,
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
musik::core::ILibraryPtr library,
|
||||
musik::core::TrackPtr firstTrack)
|
||||
{
|
||||
std::shared_ptr<Adapter> adapter(new Adapter());
|
||||
adapter->AddEntry(_TSTR("playqueue_overlay_album_jump_to"));
|
||||
adapter->AddEntry(_TSTR("playqueue_overlay_add_to_end_in_queue"));
|
||||
adapter->AddEntry(_TSTR("playqueue_overlay_add_as_next_in_queue"));
|
||||
adapter->SetSelectable(true);
|
||||
|
||||
std::shared_ptr<ListOverlay> dialog(new ListOverlay());
|
||||
|
||||
dialog->SetAdapter(adapter)
|
||||
.SetTitle(_TSTR("playqueue_overlay_album_header"))
|
||||
.SetWidth(_DIMEN("playqueue_album_header_overlay", DEFAULT_OVERLAY_WIDTH))
|
||||
.SetSelectedIndex(0)
|
||||
.SetItemSelectedCallback(
|
||||
[&playback, library, &messageQueue, firstTrack]
|
||||
(ListOverlay* overlay, IScrollAdapterPtr adapter, size_t index) {
|
||||
if (index == ListWindow::NO_SELECTION) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto albumIdColumn = library::constants::Track::ALBUM_ID;
|
||||
auto albumColumn = library::constants::Track::ALBUM;
|
||||
auto albumId = firstTrack->GetUint64(albumIdColumn);
|
||||
|
||||
if (index == 0) {
|
||||
messageQueue.Broadcast(runtime::Message::Create(
|
||||
nullptr, PlayQueueOverlays::BROADCAST_JUMP_TO_ALBUM, albumId));
|
||||
}
|
||||
else {
|
||||
handleAddCategorySelection(playback, library, albumColumn, albumId, index - 1);
|
||||
}
|
||||
});
|
||||
|
||||
cursespp::App::Overlays().Push(dialog);
|
||||
}
|
||||
|
||||
void PlayQueueOverlays::ShowLoadPlaylistOverlay(
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
musik::core::ILibraryPtr library,
|
||||
|
@ -43,11 +43,13 @@ namespace musik {
|
||||
namespace box {
|
||||
class PlayQueueOverlays {
|
||||
public:
|
||||
static const int BROADCAST_JUMP_TO_ALBUM = 3000;
|
||||
|
||||
using PlaylistSelectedCallback = std::function<void(DBID)>;
|
||||
|
||||
static void ShowAddTrackOverlay(
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
musik::box::TrackListView& trackList);
|
||||
unsigned long long trackId);
|
||||
|
||||
static void ShowAddCategoryOverlay(
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
@ -55,6 +57,12 @@ namespace musik {
|
||||
const std::string& fieldColumn,
|
||||
DBID fieldId);
|
||||
|
||||
static void ShowAlbumDividerOverlay(
|
||||
musik::core::runtime::IMessageQueue& messageQueue,
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
musik::core::ILibraryPtr library,
|
||||
musik::core::TrackPtr firstTrack);
|
||||
|
||||
static void ShowLoadPlaylistOverlay(
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
musik::core::ILibraryPtr library,
|
||||
|
@ -50,8 +50,14 @@ namespace musik {
|
||||
auto tracks = trackList->GetTrackList();
|
||||
|
||||
if (tracks && tracks->Count()) {
|
||||
size_t index = (focused.get() == trackList.get())
|
||||
? trackList->GetSelectedIndex() : 0;
|
||||
size_t index = 0;
|
||||
if (focused.get() == trackList.get()) {
|
||||
index = trackList->GetSelectedTrackIndex();
|
||||
|
||||
if (index == cursespp::ListWindow::NO_SELECTION) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
playback.Play(*tracks, index);
|
||||
}
|
||||
|
@ -1,77 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "EntryWithHeader.h"
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <cursespp/Text.h>
|
||||
|
||||
using namespace musik::box;
|
||||
using namespace cursespp;
|
||||
|
||||
EntryWithHeader::EntryWithHeader(
|
||||
const std::string& header, const std::string& value)
|
||||
{
|
||||
this->header = header;
|
||||
this->value = value;
|
||||
this->attrs = -1;
|
||||
}
|
||||
|
||||
void EntryWithHeader::SetWidth(size_t width) {
|
||||
this->width = width;
|
||||
}
|
||||
|
||||
int64 EntryWithHeader::GetAttrs(size_t line) {
|
||||
return (line == 0) ? this->headerAttrs : this->attrs;
|
||||
}
|
||||
|
||||
void EntryWithHeader::SetAttrs(int64 headerAttrs, int64 attrs) {
|
||||
this->headerAttrs = headerAttrs;
|
||||
this->attrs = attrs;
|
||||
}
|
||||
|
||||
size_t EntryWithHeader::GetLineCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
#define TRUNCATE(value, width) \
|
||||
u8substr(value, 0, width > 0 ? width : 0)
|
||||
|
||||
std::string EntryWithHeader::GetLine(size_t line) {
|
||||
if (line == 0) {
|
||||
return text::Ellipsize(this->header, this->width);
|
||||
}
|
||||
|
||||
return TRUNCATE(this->value, this->width);
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <cursespp/IScrollAdapter.h>
|
||||
|
||||
namespace musik {
|
||||
namespace box {
|
||||
class EntryWithHeader : public cursespp::IScrollAdapter::IEntry {
|
||||
public:
|
||||
EntryWithHeader(const std::string& header, const std::string& value);
|
||||
virtual ~EntryWithHeader() { }
|
||||
|
||||
virtual void SetWidth(size_t width);
|
||||
virtual int64 GetAttrs(size_t line);
|
||||
virtual size_t GetLineCount();
|
||||
virtual std::string GetLine(size_t line);
|
||||
|
||||
void SetAttrs(int64 headerAttrs, int64 attrs);
|
||||
|
||||
private:
|
||||
size_t width;
|
||||
std::string header, value;
|
||||
int64 headerAttrs, attrs;
|
||||
};
|
||||
}
|
||||
}
|
@ -44,7 +44,7 @@
|
||||
#include <glue/util/Duration.h>
|
||||
|
||||
#include <app/util/Hotkeys.h>
|
||||
#include <app/window/EntryWithHeader.h>
|
||||
#include <app/overlay/PlayQueueOverlays.h>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
@ -109,14 +109,14 @@ void TrackListView::Requery(std::shared_ptr<TrackListQueryBase> query) {
|
||||
void TrackListView::OnQueryCompleted(IQuery* query) {
|
||||
if (this->query && query == this->query.get()) {
|
||||
if (this->query->GetStatus() == IQuery::Finished) {
|
||||
this->metadata = this->query->GetResult();
|
||||
this->headers = this->query->GetHeaders();
|
||||
this->tracks = this->query->GetResult();
|
||||
this->headers.Set(this->query->GetHeaders());
|
||||
|
||||
/* if the query was functionally the same as the last query, don't
|
||||
mess with the selected index */
|
||||
if (this->lastQueryHash != this->query->GetQueryHash()) {
|
||||
this->SetSelectedIndex(0);
|
||||
this->ScrollToTop();
|
||||
this->SetSelectedIndex(this->headers.HeaderAt(0) ? 1 : 0);
|
||||
}
|
||||
|
||||
this->lastQueryHash = this->query->GetQueryHash();
|
||||
@ -130,12 +130,12 @@ void TrackListView::OnQueryCompleted(IQuery* query) {
|
||||
}
|
||||
|
||||
std::shared_ptr<const TrackList> TrackListView::GetTrackList() {
|
||||
return this->metadata;
|
||||
return this->tracks;
|
||||
}
|
||||
|
||||
void TrackListView::SetTrackList(std::shared_ptr<const TrackList> trackList) {
|
||||
if (this->metadata != trackList) {
|
||||
this->metadata = trackList;
|
||||
if (this->tracks != trackList) {
|
||||
this->tracks = trackList;
|
||||
this->SetSelectedIndex(0);
|
||||
this->ScrollToTop();
|
||||
this->OnAdapterChanged();
|
||||
@ -147,24 +147,34 @@ void TrackListView::SetTrackList(std::shared_ptr<const TrackList> trackList) {
|
||||
|
||||
void TrackListView::Clear() {
|
||||
this->query.reset();
|
||||
this->metadata.reset(new TrackList(this->library));
|
||||
this->headers.reset(new std::set<size_t>());
|
||||
this->tracks.reset(new TrackList(this->library));
|
||||
this->headers.Reset();
|
||||
this->OnAdapterChanged();
|
||||
}
|
||||
|
||||
TrackPtr TrackListView::Get(size_t index) {
|
||||
return this->metadata->Get(index);
|
||||
TrackPtr TrackListView::GetSelectedTrack() {
|
||||
auto i = this->GetSelectedTrackIndex();
|
||||
return (i == ListWindow::NO_SELECTION) ? TrackPtr() : this->tracks->Get(i);
|
||||
}
|
||||
|
||||
size_t TrackListView::GetSelectedTrackIndex() {
|
||||
auto i = this->GetSelectedIndex();
|
||||
if (i != ListWindow::NO_SELECTION) {
|
||||
auto entry = adapter->GetEntry(this, i);
|
||||
return static_cast<TrackListEntry*>(entry.get())->GetIndex();
|
||||
}
|
||||
return ListWindow::NO_SELECTION;
|
||||
}
|
||||
|
||||
size_t TrackListView::Count() {
|
||||
return this->metadata ? this->metadata->Count() : 0;
|
||||
return this->tracks ? this->tracks->Count() : 0;
|
||||
}
|
||||
|
||||
void TrackListView::ScrollToPlaying() {
|
||||
if (this->playing && this->metadata) {
|
||||
if (this->playing && this->tracks) {
|
||||
DBID id = this->playing->GetId();
|
||||
for (size_t i = 0; i < this->metadata->Count(); i++) {
|
||||
if (this->metadata->GetId(i) == id) {
|
||||
for (size_t i = 0; i < this->tracks->Count(); i++) {
|
||||
if (this->tracks->GetId(i) == id) {
|
||||
this->SetSelectedIndex(i);
|
||||
|
||||
auto pos = this->GetScrollPosition();
|
||||
@ -188,12 +198,30 @@ void TrackListView::ProcessMessage(IMessage &message) {
|
||||
bool TrackListView::KeyPress(const std::string& key) {
|
||||
bool handled = false;
|
||||
|
||||
if (Hotkeys::Is(Hotkeys::NavigateJumpToPlaying, key)) {
|
||||
if (key == "KEY_ENTER") {
|
||||
if (headers.HeaderAt(this->GetSelectedIndex())) {
|
||||
auto track = this->GetSelectedTrack();
|
||||
|
||||
PlayQueueOverlays::ShowAlbumDividerOverlay(
|
||||
MessageQueue(), this->playback, this->library, track);
|
||||
|
||||
//PlayQueueOverlays::ShowAddCategoryOverlay(
|
||||
// this->playback,
|
||||
// this->library,
|
||||
// constants::Track::ALBUM,
|
||||
// track->GetUint64(constants::Track::ALBUM_ID));
|
||||
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
else if (Hotkeys::Is(Hotkeys::NavigateJumpToPlaying, key)) {
|
||||
this->ScrollToPlaying();
|
||||
handled = true;
|
||||
}
|
||||
|
||||
handled = ListWindow::KeyPress(key);
|
||||
if (!handled) {
|
||||
handled = ListWindow::KeyPress(key);
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
this->lastChanged = now();
|
||||
@ -224,8 +252,54 @@ TrackListView::Adapter::Adapter(TrackListView &parent)
|
||||
: parent(parent) {
|
||||
}
|
||||
|
||||
/* * * * TrackListView::HeaderCalculator * * * */
|
||||
|
||||
void TrackListView::HeaderCalculator::Set(Headers rawOffsets) {
|
||||
this->rawOffsets = rawOffsets;
|
||||
this->absoluteOffsets.reset();
|
||||
if (rawOffsets) {
|
||||
this->absoluteOffsets.reset(new std::set<size_t>());
|
||||
size_t i = 0;
|
||||
for (auto val : (*this->rawOffsets)) {
|
||||
this->absoluteOffsets->insert(val + i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TrackListView::HeaderCalculator::Reset() {
|
||||
this->absoluteOffsets.reset();
|
||||
this->rawOffsets.reset();
|
||||
}
|
||||
|
||||
size_t TrackListView::HeaderCalculator::OffsetTrackIndex(size_t index) {
|
||||
size_t result = index;
|
||||
if (this->absoluteOffsets) {
|
||||
for (auto offset : (*this->absoluteOffsets)) {
|
||||
if (result != 0 && offset <= index) {
|
||||
--result;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t TrackListView::HeaderCalculator::Count() {
|
||||
return this->absoluteOffsets ? this->absoluteOffsets->size() : 0;
|
||||
}
|
||||
|
||||
bool TrackListView::HeaderCalculator::HeaderAt(size_t index) {
|
||||
return this->absoluteOffsets &&
|
||||
this->absoluteOffsets->find(index) != this->absoluteOffsets->end();
|
||||
}
|
||||
|
||||
/* * * * TrackListView::Adapter * * * */
|
||||
|
||||
size_t TrackListView::Adapter::GetEntryCount() {
|
||||
return parent.metadata ? parent.metadata->Count() : 0;
|
||||
return parent.tracks ? parent.tracks->Count() + parent.headers.Count() : 0;
|
||||
}
|
||||
|
||||
#define TRACK_COL_WIDTH 3
|
||||
@ -267,8 +341,28 @@ static std::string formatWithoutAlbum(TrackPtr track, size_t width) {
|
||||
% trackNum % title % duration % artist);
|
||||
}
|
||||
|
||||
IScrollAdapter::EntryPtr TrackListView::Adapter::GetEntry(cursespp::ScrollableWindow* window, size_t index) {
|
||||
TrackPtr track = parent.metadata->Get(index);
|
||||
IScrollAdapter::EntryPtr TrackListView::Adapter::GetEntry(cursespp::ScrollableWindow* window, size_t rawIndex) {
|
||||
bool selected = (rawIndex == parent.GetSelectedIndex());
|
||||
|
||||
if (this->parent.headers.HeaderAt(rawIndex)) {
|
||||
/* the next track at the next logical index will have the album
|
||||
tracks we're interesetd in. */
|
||||
auto trackIndex = this->parent.headers.OffsetTrackIndex(rawIndex + 1);
|
||||
TrackPtr track = parent.tracks->Get(trackIndex);
|
||||
std::string album = track->GetValue(constants::Track::ALBUM);
|
||||
|
||||
std::shared_ptr<TrackListEntry> entry(new
|
||||
TrackListEntry(album, trackIndex, RowType::Separator));
|
||||
|
||||
entry->SetAttrs(selected
|
||||
? COLOR_PAIR(CURSESPP_LIST_ITEM_HIGHLIGHTED_HEADER)
|
||||
: COLOR_PAIR(CURSESPP_LIST_ITEM_HEADER));
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
size_t trackIndex = this->parent.headers.OffsetTrackIndex(rawIndex);
|
||||
TrackPtr track = parent.tracks->Get(trackIndex);
|
||||
|
||||
if (!track) {
|
||||
return MISSING_ENTRY;
|
||||
@ -277,11 +371,9 @@ IScrollAdapter::EntryPtr TrackListView::Adapter::GetEntry(cursespp::ScrollableWi
|
||||
int64 attrs = CURSESPP_DEFAULT_COLOR;
|
||||
|
||||
if (parent.decorator) {
|
||||
attrs = parent.decorator(track, index);
|
||||
attrs = parent.decorator(track, trackIndex);
|
||||
}
|
||||
else {
|
||||
bool selected = index == parent.GetSelectedIndex();
|
||||
|
||||
attrs = selected
|
||||
? COLOR_PAIR(CURSESPP_HIGHLIGHTED_LIST_ITEM)
|
||||
: CURSESPP_DEFAULT_COLOR;
|
||||
@ -304,15 +396,10 @@ IScrollAdapter::EntryPtr TrackListView::Adapter::GetEntry(cursespp::ScrollableWi
|
||||
? parent.formatter(track, this->GetWidth())
|
||||
: formatWithoutAlbum(track, this->GetWidth());
|
||||
|
||||
if (this->parent.headers && this->parent.headers->find(index) != this->parent.headers->end()) {
|
||||
std::string album = track->GetValue(constants::Track::ALBUM);
|
||||
std::shared_ptr<EntryWithHeader> entry(new EntryWithHeader(album, text));
|
||||
entry->SetAttrs(COLOR_PAIR(CURSESPP_LIST_ITEM_HEADER), attrs);
|
||||
return entry;
|
||||
}
|
||||
else {
|
||||
std::shared_ptr<SingleLineEntry> entry(new SingleLineEntry(text));
|
||||
entry->SetAttrs(attrs);
|
||||
return entry;
|
||||
}
|
||||
std::shared_ptr<TrackListEntry> entry(
|
||||
new TrackListEntry(text, trackIndex, RowType::Track));
|
||||
|
||||
entry->SetAttrs(attrs);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <cursespp/ScrollAdapterBase.h>
|
||||
#include <cursespp/IKeyHandler.h>
|
||||
#include <cursespp/ListWindow.h>
|
||||
#include <cursespp/SingleLineEntry.h>
|
||||
|
||||
#include <core/library/query/local/TrackListQueryBase.h>
|
||||
#include <core/audio/PlaybackService.h>
|
||||
@ -55,8 +56,10 @@ namespace musik {
|
||||
public sigslot::has_slots<>
|
||||
{
|
||||
public:
|
||||
/* events */
|
||||
sigslot::signal1<musik::core::db::local::TrackListQueryBase*> Requeried;
|
||||
|
||||
/* types */
|
||||
typedef std::function<std::string(
|
||||
musik::core::TrackPtr, size_t)> RowFormatter;
|
||||
|
||||
@ -65,8 +68,27 @@ namespace musik {
|
||||
|
||||
typedef std::shared_ptr<std::set<size_t> > Headers;
|
||||
|
||||
enum class RowType : char { Track = 't', Separator = 's' };
|
||||
|
||||
/* our special type of list entry */
|
||||
class TrackListEntry : public cursespp::SingleLineEntry {
|
||||
public:
|
||||
TrackListEntry(const std::string& str, int index, RowType type)
|
||||
: cursespp::SingleLineEntry(str), index(index), type(type) { }
|
||||
|
||||
virtual ~TrackListEntry() { }
|
||||
|
||||
RowType GetType() { return type; }
|
||||
int GetIndex() { return index; }
|
||||
|
||||
private:
|
||||
RowType type;
|
||||
int index;
|
||||
};
|
||||
|
||||
typedef musik::core::db::local::TrackListQueryBase TrackListQueryBase;
|
||||
|
||||
/* ctor, dtor */
|
||||
TrackListView(
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
musik::core::ILibraryPtr library,
|
||||
@ -75,14 +97,16 @@ namespace musik {
|
||||
|
||||
virtual ~TrackListView();
|
||||
|
||||
/* IWindow */
|
||||
virtual void ProcessMessage(musik::core::runtime::IMessage &message);
|
||||
virtual bool KeyPress(const std::string& key);
|
||||
|
||||
/* regular methods */
|
||||
std::shared_ptr<const musik::core::TrackList> GetTrackList();
|
||||
void SetTrackList(std::shared_ptr<const musik::core::TrackList> trackList);
|
||||
|
||||
musik::core::TrackPtr GetSelectedTrack();
|
||||
size_t GetSelectedTrackIndex();
|
||||
void Clear();
|
||||
musik::core::TrackPtr Get(size_t index);
|
||||
size_t Count();
|
||||
|
||||
void Requery(std::shared_ptr<TrackListQueryBase> query);
|
||||
@ -105,12 +129,26 @@ namespace musik {
|
||||
};
|
||||
|
||||
private:
|
||||
/* class to help with header offset calculation */
|
||||
class HeaderCalculator {
|
||||
public:
|
||||
void Set(Headers rawOffsets);
|
||||
void Reset();
|
||||
size_t OffsetTrackIndex(size_t index);
|
||||
bool HeaderAt(size_t index);
|
||||
size_t Count();
|
||||
|
||||
private:
|
||||
Headers absoluteOffsets;
|
||||
Headers rawOffsets;
|
||||
};
|
||||
|
||||
void OnTrackChanged(size_t index, musik::core::TrackPtr track);
|
||||
void ScrollToPlaying();
|
||||
|
||||
std::shared_ptr<TrackListQueryBase> query;
|
||||
std::shared_ptr<const musik::core::TrackList> metadata;
|
||||
Headers headers;
|
||||
std::shared_ptr<const musik::core::TrackList> tracks;
|
||||
HeaderCalculator headers;
|
||||
Adapter* adapter;
|
||||
musik::core::audio::PlaybackService& playback;
|
||||
musik::core::TrackPtr playing;
|
||||
|
@ -66,12 +66,14 @@ indicies we'll use to store them */
|
||||
#define THEME_COLOR_BANNER_FOREGROUND 38
|
||||
#define THEME_COLOR_LIST_HEADER_BACKGROUND 39
|
||||
#define THEME_COLOR_LIST_HEADER_FOREGROUND 40
|
||||
#define THEME_COLOR_LIST_ITEM_HIGHLIGHTED_BACKGROUND 41
|
||||
#define THEME_COLOR_LIST_ITEM_HIGHLIGHTED_FOREGROUND 42
|
||||
#define THEME_COLOR_LIST_ITEM_ACTIVE_BACKGROUND 43
|
||||
#define THEME_COLOR_LIST_ITEM_ACTIVE_FOREGROUND 44
|
||||
#define THEME_COLOR_LIST_ITEM_ACTIVE_HIGHLIGHTED_BACKGROUND 45
|
||||
#define THEME_COLOR_LIST_ITEM_ACTIVE_HIGHLIGHTED_FOREGROUND 46
|
||||
#define THEME_COLOR_LIST_HEADER_HIGHLIGHTED_BACKGROUND 41
|
||||
#define THEME_COLOR_LIST_HEADER_HIGHLIGHTED_FOREGROUND 42
|
||||
#define THEME_COLOR_LIST_ITEM_HIGHLIGHTED_BACKGROUND 43
|
||||
#define THEME_COLOR_LIST_ITEM_HIGHLIGHTED_FOREGROUND 44
|
||||
#define THEME_COLOR_LIST_ITEM_ACTIVE_BACKGROUND 45
|
||||
#define THEME_COLOR_LIST_ITEM_ACTIVE_FOREGROUND 46
|
||||
#define THEME_COLOR_LIST_ITEM_ACTIVE_HIGHLIGHTED_BACKGROUND 47
|
||||
#define THEME_COLOR_LIST_ITEM_ACTIVE_HIGHLIGHTED_FOREGROUND 48
|
||||
|
||||
/* user-readable names for the color identifiers above. these are
|
||||
used as key names in the config files */
|
||||
@ -100,6 +102,8 @@ used as key names in the config files */
|
||||
#define JSON_KEY_COLOR_BANNER_FOREGROUND "banner_foreground"
|
||||
#define JSON_KEY_COLOR_LIST_HEADER_BACKGROUND "list_header_background"
|
||||
#define JSON_KEY_COLOR_LIST_HEADER_FOREGROUND "list_header_foreground"
|
||||
#define JSON_KEY_COLOR_LIST_HEADER_HIGHLIGHTED_BACKGROUND "list_header_highlighted_background"
|
||||
#define JSON_KEY_COLOR_LIST_HEADER_HIGHLIGHTED_FOREGROUND "list_header_highlighted_foreground"
|
||||
#define JSON_KEY_COLOR_LIST_ITEM_HIGHLIGHTED_BACKGROUND "list_item_highlighted_background"
|
||||
#define JSON_KEY_COLOR_LIST_ITEM_HIGHLIGHTED_FOREGROUND "list_item_highlighted_foreground"
|
||||
#define JSON_KEY_COLOR_LIST_ITEM_ACTIVE_BACKGROUND "list_item_active_background"
|
||||
@ -282,6 +286,8 @@ struct Theme {
|
||||
/* listview */
|
||||
listHeaderBackground.Set(THEME_COLOR_LIST_HEADER_BACKGROUND, 36, 36, 31, -1);
|
||||
listHeaderForeground.Set(THEME_COLOR_LIST_HEADER_FOREGROUND, 166, 226, 46, COLOR_256_GREEN);
|
||||
listHeaderHighlightedBackground.Set(THEME_COLOR_LIST_HEADER_HIGHLIGHTED_BACKGROUND, 166, 226, 46, COLOR_256_GREEN);
|
||||
listHeaderHighlightedForeground.Set(THEME_COLOR_LIST_HEADER_HIGHLIGHTED_FOREGROUND, 36, 36, 31, COLOR_BLACK);
|
||||
listHighlightedBackground.Set(THEME_COLOR_LIST_ITEM_HIGHLIGHTED_BACKGROUND, 166, 226, 46, COLOR_256_GREEN);
|
||||
listHighlightedForeground.Set(THEME_COLOR_LIST_ITEM_HIGHLIGHTED_FOREGROUND, 24, 24, 20, COLOR_BLACK);
|
||||
listActiveBackground.Set(THEME_COLOR_LIST_ITEM_ACTIVE_BACKGROUND, 66, 66, 56, COLOR_256_MEDIUM_GRAY);
|
||||
@ -336,6 +342,8 @@ struct Theme {
|
||||
this->bannerForeground.Set(colors.value(JSON_KEY_COLOR_BANNER_FOREGROUND, unset));
|
||||
this->listHeaderBackground.Set(colors.value(JSON_KEY_COLOR_LIST_HEADER_BACKGROUND, unset));
|
||||
this->listHeaderForeground.Set(colors.value(JSON_KEY_COLOR_LIST_HEADER_FOREGROUND, unset));
|
||||
this->listHeaderHighlightedBackground.Set(colors.value(JSON_KEY_COLOR_LIST_HEADER_HIGHLIGHTED_BACKGROUND, unset));
|
||||
this->listHeaderHighlightedForeground.Set(colors.value(JSON_KEY_COLOR_LIST_HEADER_HIGHLIGHTED_FOREGROUND, unset));
|
||||
this->listHighlightedBackground.Set(colors.value(JSON_KEY_COLOR_LIST_ITEM_HIGHLIGHTED_BACKGROUND, unset));
|
||||
this->listHighlightedForeground.Set(colors.value(JSON_KEY_COLOR_LIST_ITEM_HIGHLIGHTED_FOREGROUND, unset));
|
||||
this->listActiveBackground.Set(colors.value(JSON_KEY_COLOR_LIST_ITEM_ACTIVE_BACKGROUND, unset));
|
||||
@ -414,6 +422,11 @@ struct Theme {
|
||||
listHeaderForeground.Id(mode, COLOR_GREEN),
|
||||
listHeaderBackground.Id(mode, -1));
|
||||
|
||||
init_pair(
|
||||
CURSESPP_LIST_ITEM_HIGHLIGHTED_HEADER,
|
||||
listHeaderHighlightedForeground.Id(mode, -1),
|
||||
listHeaderHighlightedBackground.Id(mode, COLOR_GREEN));
|
||||
|
||||
init_pair(
|
||||
CURSESPP_SELECTED_LIST_ITEM,
|
||||
listActiveForeground.Id(mode, COLOR_YELLOW),
|
||||
@ -468,6 +481,8 @@ struct Theme {
|
||||
/* listview */
|
||||
Color listHeaderBackground;
|
||||
Color listHeaderForeground;
|
||||
Color listHeaderHighlightedBackground;
|
||||
Color listHeaderHighlightedForeground;
|
||||
Color listHighlightedBackground;
|
||||
Color listHighlightedForeground;
|
||||
Color listActiveForeground;
|
||||
|
@ -42,30 +42,31 @@
|
||||
#define CURSESPP_HIGHLIGHTED_LIST_ITEM 2
|
||||
#define CURSESPP_HIGHLIGHTED_SELECTED_LIST_ITEM 3
|
||||
#define CURSESPP_LIST_ITEM_HEADER 4
|
||||
#define CURSESPP_LIST_ITEM_HIGHLIGHTED_HEADER 5
|
||||
|
||||
#define CURSESPP_DEFAULT_CONTENT_COLOR 5
|
||||
#define CURSESPP_DEFAULT_FRAME_COLOR 6
|
||||
#define CURSESPP_FOCUSED_FRAME_COLOR 7
|
||||
#define CURSESPP_DEFAULT_CONTENT_COLOR 6
|
||||
#define CURSESPP_DEFAULT_FRAME_COLOR 7
|
||||
#define CURSESPP_FOCUSED_FRAME_COLOR 8
|
||||
|
||||
#define CURSESPP_TEXT_DEFAULT 8
|
||||
#define CURSESPP_TEXT_DISABLED 9
|
||||
#define CURSESPP_TEXT_FOCUSED 10
|
||||
#define CURSESPP_TEXT_ACTIVE 11
|
||||
#define CURSESPP_TEXT_WARNING 12
|
||||
#define CURSESPP_TEXT_ERROR 13
|
||||
#define CURSESPP_TEXT_HIDDEN 14
|
||||
#define CURSESPP_TEXT_DEFAULT 9
|
||||
#define CURSESPP_TEXT_DISABLED 10
|
||||
#define CURSESPP_TEXT_FOCUSED 11
|
||||
#define CURSESPP_TEXT_ACTIVE 12
|
||||
#define CURSESPP_TEXT_WARNING 13
|
||||
#define CURSESPP_TEXT_ERROR 14
|
||||
#define CURSESPP_TEXT_HIDDEN 15
|
||||
|
||||
#define CURSESPP_BUTTON_NORMAL 16
|
||||
#define CURSESPP_BUTTON_HIGHLIGHTED 18
|
||||
#define CURSESPP_BUTTON_HIGHLIGHTED 17
|
||||
|
||||
#define CURSESPP_SHORTCUT_ROW_NORMAL 19
|
||||
#define CURSESPP_SHORTCUT_ROW_FOCUSED 20
|
||||
#define CURSESPP_SHORTCUT_ROW_NORMAL 18
|
||||
#define CURSESPP_SHORTCUT_ROW_FOCUSED 19
|
||||
|
||||
#define CURSESPP_OVERLAY_FRAME 21
|
||||
#define CURSESPP_OVERLAY_CONTENT 22
|
||||
#define CURSESPP_OVERLAY_INPUT_FRAME 23
|
||||
#define CURSESPP_OVERLAY_FRAME 20
|
||||
#define CURSESPP_OVERLAY_CONTENT 21
|
||||
#define CURSESPP_OVERLAY_INPUT_FRAME 22
|
||||
|
||||
#define CURSESPP_BANNER 24
|
||||
#define CURSESPP_BANNER 23
|
||||
|
||||
namespace cursespp {
|
||||
class Colors {
|
||||
|
@ -48,7 +48,7 @@ namespace cursespp {
|
||||
virtual std::string GetLine(size_t line);
|
||||
|
||||
void SetAttrs(int64 attrs);
|
||||
|
||||
|
||||
private:
|
||||
size_t width;
|
||||
std::string value;
|
||||
|
@ -203,12 +203,20 @@ void Window::SetParent(IWindow* parent) {
|
||||
if (this->parent != parent) {
|
||||
IWindowGroup* group = dynamic_cast<IWindowGroup*>(this->parent);
|
||||
|
||||
IWindow* oldParent = this->parent;
|
||||
this->parent = parent;
|
||||
|
||||
if (this->frame) {
|
||||
this->Hide();
|
||||
this->Show();
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
this->OnAddedToParent(parent);
|
||||
}
|
||||
else {
|
||||
this->OnRemovedFromParent(oldParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,6 +291,14 @@ void Window::OnRedraw() {
|
||||
/* for subclass use */
|
||||
}
|
||||
|
||||
void Window::OnAddedToParent(IWindow* newParent) {
|
||||
/* for subclass use */
|
||||
}
|
||||
|
||||
void Window::OnRemovedFromParent(IWindow* oldParent) {
|
||||
/* for subclass use */
|
||||
}
|
||||
|
||||
void Window::Redraw() {
|
||||
this->isDirty = true;
|
||||
|
||||
@ -450,7 +466,7 @@ void Window::OnParentVisibilityChanged(bool visible) {
|
||||
this->Destroy();
|
||||
}
|
||||
|
||||
this->OnVisibilityChanged(false);
|
||||
//this->OnVisibilityChanged(false);
|
||||
}
|
||||
else if (visible && this->isVisible) {
|
||||
if (this->framePanel) {
|
||||
@ -460,7 +476,7 @@ void Window::OnParentVisibilityChanged(bool visible) {
|
||||
this->Recreate();
|
||||
}
|
||||
|
||||
this->OnVisibilityChanged(true);
|
||||
//this->OnVisibilityChanged(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,6 +138,8 @@ namespace cursespp {
|
||||
virtual void OnVisibilityChanged(bool visible);
|
||||
virtual void OnFocusChanged(bool focused);
|
||||
virtual void OnRedraw();
|
||||
virtual void OnAddedToParent(IWindow* newParent);
|
||||
virtual void OnRemovedFromParent(IWindow* oldParent);
|
||||
|
||||
private:
|
||||
IWindow* parent;
|
||||
|
@ -57,6 +57,11 @@
|
||||
"playqueue_overlay_new_playlist_name_title": "new playlist name",
|
||||
"playqueue_overlay_confirm_delete_message": "are you sure you want to delete '%s'?",
|
||||
"playqueue_overlay_load_playlists_none_message": "you haven't saved any playlists yet!",
|
||||
"playqueue_overlay_album_header": "album actions",
|
||||
"playqueue_overlay_album_jump_to": "jump to album in library",
|
||||
"playqueue_overlay_add_to_end_in_queue": "add to end of play queue",
|
||||
"playqueue_overlay_add_as_next_in_queue": "add as next in play queue",
|
||||
|
||||
|
||||
"visualizer_overlay_title": "visualizers",
|
||||
"visualizer_overlay_no_visualizers_message": "no visualizers found!",
|
||||
@ -85,5 +90,12 @@
|
||||
"transport_repeat_off": "repeat off",
|
||||
|
||||
"main_syncing_banner": "syncing metadata (%d tracks processed)"
|
||||
},
|
||||
|
||||
"dimensions": {
|
||||
"playqueue_album_header_overlay": 35,
|
||||
"playqueue_playlist_add_to_queue_overlay": 30,
|
||||
"playqueue_playlist_list_overlay": 30,
|
||||
"playqueue_playlist_name_overlay": 30
|
||||
}
|
||||
}
|
@ -101,6 +101,14 @@
|
||||
"list_header_foreground": {
|
||||
"hex": "#859900",
|
||||
"palette": 64
|
||||
},
|
||||
"list_header_highlighted_background": {
|
||||
"hex": "#859900",
|
||||
"palette": 64
|
||||
},
|
||||
"list_header_highlighted_foreground": {
|
||||
"hex": "#002b36",
|
||||
"palette": 234
|
||||
},
|
||||
"list_item_highlighted_background": {
|
||||
"hex": "#93a1a1",
|
||||
|
@ -102,6 +102,14 @@
|
||||
"hex": "#859900",
|
||||
"palette": 64
|
||||
},
|
||||
"list_header_highlighted_background": {
|
||||
"hex": "#859900",
|
||||
"palette": 64
|
||||
},
|
||||
"list_header_highlighted_foreground": {
|
||||
"hex": "#fdf6e3",
|
||||
"palette": 230
|
||||
},
|
||||
"list_item_highlighted_background": {
|
||||
"hex": "#93a1a1",
|
||||
"palette": 245
|
||||
|
@ -149,7 +149,6 @@ xcopy "$(ProjectDir)data\locales\*" "$(TargetDir)locales\" /Y /e</Command>
|
||||
<ClCompile Include="app\util\Playback.cpp" />
|
||||
<ClCompile Include="app\util\PreferenceKeys.cpp" />
|
||||
<ClCompile Include="app\window\CategoryListView.cpp" />
|
||||
<ClCompile Include="app\window\EntryWithHeader.cpp" />
|
||||
<ClCompile Include="app\window\LogWindow.cpp" />
|
||||
<ClCompile Include="app\window\TrackListView.cpp" />
|
||||
<ClCompile Include="app\window\TransportWindow.cpp" />
|
||||
@ -203,7 +202,6 @@ xcopy "$(ProjectDir)data\locales\*" "$(TargetDir)locales\" /Y /e</Command>
|
||||
<ClInclude Include="app\util\PreferenceKeys.h" />
|
||||
<ClInclude Include="app\util\Version.h" />
|
||||
<ClInclude Include="app\window\CategoryListView.h" />
|
||||
<ClInclude Include="app\window\EntryWithHeader.h" />
|
||||
<ClInclude Include="app\window\LogWindow.h" />
|
||||
<ClInclude Include="app\window\TrackListView.h" />
|
||||
<ClInclude Include="app\window\TransportWindow.h" />
|
||||
|
@ -48,9 +48,6 @@
|
||||
<ClCompile Include="app\util\GlobalHotkeys.cpp">
|
||||
<Filter>app\util</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="app\window\EntryWithHeader.cpp">
|
||||
<Filter>app\window</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="app\layout\ConsoleLayout.cpp">
|
||||
<Filter>app\layout</Filter>
|
||||
</ClCompile>
|
||||
@ -219,9 +216,6 @@
|
||||
<ClInclude Include="cursespp\IOrderable.h">
|
||||
<Filter>cursespp</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="app\window\EntryWithHeader.h">
|
||||
<Filter>app\window</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="app\layout\ConsoleLayout.h">
|
||||
<Filter>app\layout</Filter>
|
||||
</ClInclude>
|
||||
|
Loading…
x
Reference in New Issue
Block a user