mirror of
https://github.com/clangen/musikcube.git
synced 2025-03-01 01:13:28 +00:00
- Cleaned up and generalized Transport event handling
- Added some virtual destructors to interfaces
This commit is contained in:
parent
483760effd
commit
2d65ab480a
@ -41,23 +41,22 @@ using namespace musik::core::audio;
|
||||
|
||||
static std::string TAG = "Player";
|
||||
|
||||
PlayerPtr Player::Create(std::string &url, OutputPtr *output) {
|
||||
return PlayerPtr(new Player(url,output));
|
||||
PlayerPtr Player::Create(std::string &url, OutputPtr output) {
|
||||
return PlayerPtr(new Player(url, output));
|
||||
}
|
||||
|
||||
Player::Player(std::string &url, OutputPtr *output)
|
||||
Player::Player(std::string &url, OutputPtr output)
|
||||
: volume(1.0)
|
||||
, state(Player::Precache)
|
||||
, url(url)
|
||||
, prebufferSizeBytes(0)
|
||||
, maxPrebufferSizeBytes(2000000)
|
||||
, currentPosition(0)
|
||||
, setPosition(-1)
|
||||
{
|
||||
, setPosition(-1) {
|
||||
musik::debug::info(TAG, "new instance created");
|
||||
|
||||
if (*output) {
|
||||
this->output = *output;
|
||||
if (output) {
|
||||
this->output = output;
|
||||
}
|
||||
else {
|
||||
/* if no output is specified, find all output plugins, and select the first one. */
|
||||
|
@ -46,18 +46,17 @@
|
||||
|
||||
namespace musik { namespace core { namespace audio {
|
||||
|
||||
class Player;
|
||||
class Transport;
|
||||
class Player;
|
||||
typedef std::shared_ptr<Player> PlayerPtr;
|
||||
|
||||
class Player : public IBufferProvider {
|
||||
public:
|
||||
typedef std::shared_ptr<IOutput> OutputPtr;
|
||||
|
||||
static PlayerPtr Create(std::string &url,OutputPtr *output = NULL);
|
||||
static PlayerPtr Create(std::string &url, OutputPtr output = OutputPtr());
|
||||
|
||||
private:
|
||||
Player(std::string &url,OutputPtr *output);
|
||||
Player(std::string &url, OutputPtr output);
|
||||
|
||||
public:
|
||||
~Player();
|
||||
@ -75,6 +74,8 @@ namespace musik { namespace core { namespace audio {
|
||||
double Volume();
|
||||
void SetVolume(double volume);
|
||||
|
||||
std::string GetUrl() const { return this->url; }
|
||||
|
||||
bool Exited();
|
||||
|
||||
public:
|
||||
@ -83,19 +84,13 @@ namespace musik { namespace core { namespace audio {
|
||||
PlayerEvent PlaybackAlmostEnded;
|
||||
PlayerEvent PlaybackEnded;
|
||||
PlayerEvent PlaybackError;
|
||||
|
||||
OutputPtr output;
|
||||
|
||||
|
||||
private:
|
||||
void ThreadLoop();
|
||||
bool PreBuffer();
|
||||
int State();
|
||||
void ReleaseAllBuffers();
|
||||
|
||||
protected:
|
||||
friend class Transport;
|
||||
std::string url;
|
||||
|
||||
private:
|
||||
typedef boost::scoped_ptr<boost::thread> ThreadPtr;
|
||||
typedef std::list<BufferPtr> BufferList;
|
||||
@ -107,10 +102,13 @@ namespace musik { namespace core { namespace audio {
|
||||
Quit = 2
|
||||
} States;
|
||||
|
||||
OutputPtr output;
|
||||
StreamPtr stream;
|
||||
ThreadPtr thread;
|
||||
BufferList lockedBuffers;
|
||||
|
||||
std::string url;
|
||||
|
||||
BufferList prebufferQueue;
|
||||
long prebufferSizeBytes;
|
||||
long maxPrebufferSizeBytes;
|
||||
|
@ -51,7 +51,7 @@ namespace musik {
|
||||
}
|
||||
|
||||
if (!active_) {
|
||||
throw stopped_exception();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
log_entry* top = queue_.front();
|
||||
@ -101,8 +101,10 @@ static void thread_proc() {
|
||||
try {
|
||||
while (!cancel_) {
|
||||
log_queue::log_entry* entry = queue_->pop_top();
|
||||
debug::string_logged(entry->level_, entry->tag_, entry->message_);
|
||||
delete entry;
|
||||
if (entry) {
|
||||
debug::string_logged(entry->level_, entry->tag_, entry->message_);
|
||||
delete entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (log_queue::stopped_exception&) {
|
||||
|
@ -12,6 +12,8 @@ namespace musik { namespace core {
|
||||
sigslot::signal0<> PathsUpdated;
|
||||
sigslot::signal0<> TrackRefreshed;
|
||||
|
||||
virtual ~IIndexer() = 0 { }
|
||||
|
||||
virtual void AddPath(const std::string& path) = 0;
|
||||
virtual void RemovePath(const std::string& path) = 0;
|
||||
virtual void GetPaths(std::vector<std::string>& paths) = 0;
|
||||
|
@ -16,6 +16,8 @@ namespace musik { namespace core {
|
||||
public:
|
||||
sigslot::signal1<QueryPtr> QueryCompleted;
|
||||
|
||||
virtual ~ILibrary() = 0 { }
|
||||
|
||||
virtual int Enqueue(QueryPtr query, unsigned int options = 0) = 0;
|
||||
virtual IIndexer *Indexer() = 0;
|
||||
virtual int Id() = 0;
|
||||
|
@ -24,6 +24,8 @@ namespace musik { namespace core {
|
||||
Finished = 4,
|
||||
} Status;
|
||||
|
||||
virtual ~IQuery() = 0 { }
|
||||
|
||||
virtual bool Run(db::Connection &db) = 0;
|
||||
virtual int GetStatus() = 0;
|
||||
virtual int GetId() = 0;
|
||||
|
@ -64,7 +64,7 @@ namespace musik { namespace core {
|
||||
const std::string& libraryPath,
|
||||
const std::string& dbFilename);
|
||||
|
||||
~Indexer();
|
||||
virtual ~Indexer();
|
||||
|
||||
virtual void AddPath(const std::string& paths);
|
||||
virtual void RemovePath(const std::string& paths);
|
||||
|
@ -41,115 +41,143 @@ using namespace musik::core::audio;
|
||||
static std::string TAG = "Transport";
|
||||
|
||||
Transport::Transport()
|
||||
:volume(1.0)
|
||||
,gapless(true)
|
||||
{
|
||||
: volume(1.0) {
|
||||
}
|
||||
|
||||
Transport::~Transport(){
|
||||
Transport::~Transport() {
|
||||
this->nextPlayer.reset();
|
||||
this->currentPlayer.reset();
|
||||
this->players.clear();
|
||||
}
|
||||
|
||||
void Transport::PrepareNextTrack(std::string trackUrl){
|
||||
void Transport::PrepareNextTrack(std::string trackUrl) {
|
||||
PlayerPtr player = Player::Create(trackUrl);
|
||||
|
||||
if(this->gapless && this->currentPlayer){
|
||||
this->nextPlayer = Player::Create(trackUrl,&this->currentPlayer->output);
|
||||
this->nextPlayer->Play();
|
||||
}else{
|
||||
this->nextPlayer = Player::Create(trackUrl);
|
||||
{
|
||||
boost::mutex::scoped_lock lock(this->stateMutex);
|
||||
this->currentPlayer = player;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Transport::Start(std::string url){
|
||||
void Transport::Start(std::string url) {
|
||||
musik::debug::info(TAG, "we were asked to start the track at " + url);
|
||||
|
||||
// Check if this is already Prepared
|
||||
PlayerPtr player = this->nextPlayer;
|
||||
this->nextPlayer.reset();
|
||||
PlayerPtr player;
|
||||
|
||||
musik::debug::info(TAG, "creating a Player...");
|
||||
{
|
||||
boost::mutex::scoped_lock lock(this->stateMutex);
|
||||
|
||||
// If the nextPlayer wasn't the same as the one started, lets create a new one
|
||||
if(!player || player->url != url){
|
||||
Player::OutputPtr output;
|
||||
PlayerPtr newPlayer = this->nextPlayer;
|
||||
this->nextPlayer.reset();
|
||||
|
||||
player = Player::Create(url, &output);
|
||||
player->SetVolume(this->volume);
|
||||
musik::debug::info(TAG, "creating a Player...");
|
||||
|
||||
musik::debug::info(TAG, "Player created successfully");
|
||||
if (!newPlayer || newPlayer->GetUrl() != url) {
|
||||
newPlayer = Player::Create(url); /* non-blocking */
|
||||
newPlayer->SetVolume(this->volume);
|
||||
musik::debug::info(TAG, "Player created successfully");
|
||||
}
|
||||
|
||||
this->currentPlayer = newPlayer;
|
||||
|
||||
this->currentPlayer->PlaybackStarted.connect(this, &Transport::OnPlaybackStarted);
|
||||
this->currentPlayer->PlaybackAlmostEnded.connect(this, &Transport::OnPlaybackAlmostEnded);
|
||||
this->currentPlayer->PlaybackEnded.connect(this, &Transport::OnPlaybackEnded);
|
||||
this->currentPlayer->PlaybackError.connect(this, &Transport::OnPlaybackError);
|
||||
|
||||
musik::debug::info(TAG, "play()");
|
||||
this->currentPlayer->Play();
|
||||
|
||||
player = this->currentPlayer;
|
||||
}
|
||||
|
||||
// Add to the players
|
||||
this->players.push_front(player);
|
||||
this->currentPlayer = player;
|
||||
|
||||
musik::debug::info(TAG, "player added to player list");
|
||||
|
||||
// Lets connect to the signals of the currentPlayer /* FIXME event binding is reversed here */
|
||||
this->currentPlayer->PlaybackStarted.connect(this,&Transport::OnPlaybackStarted);
|
||||
this->currentPlayer->PlaybackAlmostEnded.connect(this,&Transport::OnPlaybackAlmostEnded);
|
||||
this->currentPlayer->PlaybackEnded.connect(this,&Transport::OnPlaybackEnded);
|
||||
this->currentPlayer->PlaybackError.connect(this, &Transport::OnPlaybackError);
|
||||
|
||||
musik::debug::info(TAG, "play()");
|
||||
|
||||
// Start playing
|
||||
player->Play();
|
||||
this->TrackStarted(url);
|
||||
this->RaisePlaybackEvent(Transport::EventScheduled, player);
|
||||
}
|
||||
|
||||
void Transport::Stop(){
|
||||
void Transport::Stop() {
|
||||
musik::debug::info(TAG, "stop");
|
||||
this->players.clear();
|
||||
this->currentPlayer.reset();
|
||||
this->nextPlayer.reset();
|
||||
this->PlaybackEnded();
|
||||
|
||||
PlayerPtr player = NULL;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(this->stateMutex);
|
||||
|
||||
player = this->currentPlayer;
|
||||
this->currentPlayer.reset();
|
||||
this->nextPlayer.reset();
|
||||
}
|
||||
|
||||
if (player) {
|
||||
this->RaisePlaybackEvent(Transport::EventFinished, player);
|
||||
}
|
||||
}
|
||||
|
||||
bool Transport::Pause(){
|
||||
bool Transport::Pause() {
|
||||
musik::debug::info(TAG, "pause");
|
||||
|
||||
// pause all players
|
||||
for(PlayerList::iterator player=this->players.begin();player!=this->players.end();++player){
|
||||
(*player)->Pause();
|
||||
PlayerPtr player;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(this->stateMutex);
|
||||
|
||||
if (this->currentPlayer) {
|
||||
this->currentPlayer->Pause();
|
||||
player = this->currentPlayer;
|
||||
}
|
||||
}
|
||||
this->PlaybackPause();
|
||||
return true;
|
||||
|
||||
if (player) {
|
||||
this->RaisePlaybackEvent(Transport::EventPaused, player);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool Transport::Resume(){
|
||||
|
||||
bool Transport::Resume() {
|
||||
musik::debug::info(TAG, "resume");
|
||||
|
||||
// Resume all players
|
||||
for(PlayerList::iterator player=this->players.begin();player!=this->players.end();++player){
|
||||
(*player)->Resume();
|
||||
PlayerPtr player;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(this->stateMutex);
|
||||
|
||||
if (this->currentPlayer) {
|
||||
this->currentPlayer->Resume();
|
||||
player = this->currentPlayer;
|
||||
}
|
||||
}
|
||||
this->PlaybackResume();
|
||||
return true;
|
||||
|
||||
if (player) {
|
||||
this->RaisePlaybackEvent(Transport::EventResumed, player);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
double Transport::Position() {
|
||||
boost::mutex::scoped_lock lock(this->stateMutex);
|
||||
|
||||
double Transport::Position(){
|
||||
if(this->currentPlayer){
|
||||
if (this->currentPlayer) {
|
||||
return this->currentPlayer->Position();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Transport::SetPosition(double seconds){
|
||||
if(this->currentPlayer){
|
||||
void Transport::SetPosition(double seconds) {
|
||||
boost::mutex::scoped_lock lock(this->stateMutex);
|
||||
|
||||
if (this->currentPlayer) {
|
||||
return this->currentPlayer->SetPosition(seconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double Transport::Volume(){
|
||||
double Transport::Volume() {
|
||||
return this->volume;
|
||||
}
|
||||
|
||||
void Transport::SetVolume(double volume){
|
||||
void Transport::SetVolume(double volume) {
|
||||
double oldVolume = this->volume;
|
||||
|
||||
volume = max(0, min(1.0, volume));
|
||||
@ -160,48 +188,90 @@ void Transport::SetVolume(double volume){
|
||||
this->VolumeChanged();
|
||||
}
|
||||
|
||||
musik::debug::info(TAG, boost::str(boost::format("set volume %d%%") % round(volume * 100)));
|
||||
musik::debug::info(TAG, boost::str(
|
||||
boost::format("set volume %d%%") % round(volume * 100)));
|
||||
|
||||
if(this->currentPlayer){
|
||||
for(PlayerList::iterator player=this->players.begin();player!=this->players.end();++player){
|
||||
(*player)->SetVolume(volume);
|
||||
{
|
||||
boost::mutex::scoped_lock lock(this->stateMutex);
|
||||
|
||||
if (this->currentPlayer) {
|
||||
this->currentPlayer->SetVolume(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Transport::OnPlaybackStarted(Player *player){
|
||||
if(this->currentPlayer.get()==player){
|
||||
this->PlaybackStarted();
|
||||
void Transport::OnPlaybackStarted(Player *player) {
|
||||
PlayerPtr playerForEvent;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(this->stateMutex);
|
||||
|
||||
if (this->currentPlayer.get() == player) {
|
||||
playerForEvent = this->currentPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
if (playerForEvent) {
|
||||
this->RaisePlaybackEvent(Transport::EventStarted, playerForEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void Transport::OnPlaybackAlmostEnded(Player *player){
|
||||
if(this->currentPlayer.get()==player){
|
||||
this->PlaybackAlmostDone();
|
||||
void Transport::OnPlaybackAlmostEnded(Player *player) {
|
||||
PlayerPtr playerForEvent;
|
||||
|
||||
// Reuse the output
|
||||
if(this->nextPlayer && this->gapless){
|
||||
// TODO
|
||||
// this->nex
|
||||
{
|
||||
boost::mutex::scoped_lock lock(this->stateMutex);
|
||||
|
||||
if (this->currentPlayer.get() == player) {
|
||||
playerForEvent = this->currentPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
this->RaisePlaybackEvent(Transport::EventAlmostDone, playerForEvent);
|
||||
}
|
||||
|
||||
void Transport::OnPlaybackEnded(Player *player){
|
||||
if(this->currentPlayer.get()==player){
|
||||
this->PlaybackEnded();
|
||||
void Transport::OnPlaybackEnded(Player *player) {
|
||||
PlayerPtr playerForEvent;
|
||||
PlayerPtr nextPlayer;
|
||||
|
||||
// If the is a nextPlayer, then we should start playing right away
|
||||
if(this->nextPlayer){
|
||||
this->Start(this->nextPlayer->url.c_str());
|
||||
{
|
||||
boost::mutex::scoped_lock lock(this->stateMutex);
|
||||
|
||||
if (this->currentPlayer.get() == player) {
|
||||
playerForEvent = this->currentPlayer;
|
||||
}
|
||||
|
||||
if (this->nextPlayer) {
|
||||
nextPlayer = this->nextPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
if (playerForEvent) {
|
||||
this->RaisePlaybackEvent(Transport::EventFinished, playerForEvent);
|
||||
}
|
||||
|
||||
if (nextPlayer) {
|
||||
this->Start(nextPlayer->GetUrl().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Transport::OnPlaybackError(Player *player) {
|
||||
this->PlaybackError();
|
||||
}
|
||||
PlayerPtr playerForEvent;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(this->stateMutex);
|
||||
|
||||
if (this->currentPlayer.get() == player) {
|
||||
playerForEvent = this->currentPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
if (playerForEvent) {
|
||||
this->RaisePlaybackEvent(Transport::EventError, playerForEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void Transport::RaisePlaybackEvent(int type, PlayerPtr player) {
|
||||
std::string uri = player ? player->GetUrl() : "";
|
||||
this->PlaybackEvent(type, uri);
|
||||
}
|
@ -37,6 +37,7 @@
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <sigslot/sigslot.h>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
namespace musik { namespace core { namespace audio {
|
||||
|
||||
@ -59,26 +60,21 @@ namespace musik { namespace core { namespace audio {
|
||||
|
||||
public:
|
||||
typedef enum {
|
||||
Started = 1,
|
||||
Ended = 2,
|
||||
Error = 3
|
||||
} PlaybackStatus;
|
||||
EventScheduled = 0,
|
||||
EventStarted = 1,
|
||||
EventPaused = 2,
|
||||
EventResumed = 3,
|
||||
EventAlmostDone = 4,
|
||||
EventFinished = 5,
|
||||
EventError = -1
|
||||
} PlaybackEventType;
|
||||
|
||||
sigslot::signal1<std::string> TrackStarted;
|
||||
sigslot::signal2<int, std::string> PlaybackEvent;
|
||||
sigslot::signal0<> VolumeChanged;
|
||||
|
||||
typedef sigslot::signal1<int> PlaybackStatusEvent;
|
||||
PlaybackStatusEvent PlaybackStatusChange;
|
||||
|
||||
typedef sigslot::signal0<> PlaybackEvent;
|
||||
PlaybackEvent PlaybackAlmostDone;
|
||||
PlaybackEvent PlaybackStarted;
|
||||
PlaybackEvent PlaybackEnded;
|
||||
PlaybackEvent PlaybackPause;
|
||||
PlaybackEvent PlaybackResume;
|
||||
PlaybackEvent PlaybackError;
|
||||
|
||||
private:
|
||||
void RaisePlaybackEvent(int type, PlayerPtr player);
|
||||
|
||||
void OnPlaybackStarted(Player *player);
|
||||
void OnPlaybackAlmostEnded(Player *player);
|
||||
void OnPlaybackEnded(Player *player);
|
||||
@ -86,10 +82,8 @@ namespace musik { namespace core { namespace audio {
|
||||
|
||||
private:
|
||||
double volume;
|
||||
bool gapless;
|
||||
|
||||
typedef std::list<PlayerPtr> PlayerList;
|
||||
PlayerList players;
|
||||
boost::mutex stateMutex;
|
||||
PlayerPtr currentPlayer;
|
||||
PlayerPtr nextPlayer;
|
||||
};
|
||||
|
@ -191,6 +191,9 @@ int main(int argc, char* argv[])
|
||||
if (ch == '\t') { /* tab */
|
||||
focusNextInLayout(state);
|
||||
}
|
||||
else if (kn == "^D") {
|
||||
quit = true;
|
||||
}
|
||||
else if (kn == "ALT_K") {
|
||||
tp.SetVolume(tp.Volume() + 0.05); /* 5% */
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ TransportWindow::TransportWindow(LibraryPtr library, Transport& transport)
|
||||
this->library = library;
|
||||
this->library->QueryCompleted.connect(this, &TransportWindow::OnQueryCompleted);
|
||||
this->transport = &transport;
|
||||
this->transport->TrackStarted.connect(this, &TransportWindow::OnTransportStarted);
|
||||
this->transport->PlaybackEvent.connect(this, &TransportWindow::OnTransportPlaybackEvent);
|
||||
this->transport->VolumeChanged.connect(this, &TransportWindow::OnTransportVolumeChanged);
|
||||
this->paused = false;
|
||||
}
|
||||
@ -48,9 +48,11 @@ void TransportWindow::ProcessMessage(IWindowMessage &message) {
|
||||
}
|
||||
}
|
||||
|
||||
void TransportWindow::OnTransportStarted(std::string url) {
|
||||
this->trackQuery.reset(new SingleTrackQuery(url));
|
||||
this->library->Enqueue(this->trackQuery);
|
||||
void TransportWindow::OnTransportPlaybackEvent(int eventType, std::string url) {
|
||||
if (eventType == Transport::EventStarted) {
|
||||
this->trackQuery.reset(new SingleTrackQuery(url));
|
||||
this->library->Enqueue(this->trackQuery);
|
||||
}
|
||||
}
|
||||
|
||||
void TransportWindow::OnTransportVolumeChanged() {
|
||||
|
@ -23,7 +23,7 @@ class TransportWindow : public Window, public sigslot::has_slots<> {
|
||||
void Update();
|
||||
|
||||
private:
|
||||
void OnTransportStarted(std::string url);
|
||||
void OnTransportPlaybackEvent(int eventType, std::string url);
|
||||
void OnTransportVolumeChanged();
|
||||
void OnQueryCompleted(QueryPtr query);
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
class IDisplayable {
|
||||
public:
|
||||
virtual ~IDisplayable() = 0 { }
|
||||
|
||||
virtual void Show() = 0;
|
||||
virtual void Hide() = 0;
|
||||
};
|
@ -4,5 +4,7 @@
|
||||
|
||||
class IInput {
|
||||
public:
|
||||
virtual ~IInput() = 0 { }
|
||||
|
||||
virtual void WriteChar(int64 ch) = 0;
|
||||
};
|
@ -4,5 +4,6 @@
|
||||
|
||||
class IKeyHandler {
|
||||
public:
|
||||
virtual ~IKeyHandler() = 0 { }
|
||||
virtual void KeyPress(int64 ch) = 0;
|
||||
};
|
@ -5,6 +5,7 @@
|
||||
|
||||
class ILayout : public IWindowGroup, public IDisplayable {
|
||||
public:
|
||||
virtual ~ILayout() = 0 { }
|
||||
virtual IWindow* FocusNext() = 0;
|
||||
virtual IWindow* FocusPrev() = 0;
|
||||
virtual IWindow* GetFocus() = 0;
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
class IScrollAdapter {
|
||||
public:
|
||||
virtual ~IScrollAdapter() = 0 { }
|
||||
|
||||
struct ScrollPosition {
|
||||
ScrollPosition() {
|
||||
firstVisibleEntryIndex = 0;
|
||||
@ -22,6 +24,7 @@ class IScrollAdapter {
|
||||
|
||||
class IEntry {
|
||||
public:
|
||||
virtual ~IEntry() = 0 { }
|
||||
virtual size_t GetLineCount() = 0;
|
||||
virtual std::string GetLine(size_t line) = 0;
|
||||
virtual std::string GetValue() = 0;
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
class IScrollable {
|
||||
public:
|
||||
virtual ~IScrollable() = 0 { }
|
||||
virtual void ScrollToTop() = 0;
|
||||
virtual void ScrollToBottom() = 0;
|
||||
virtual void ScrollUp(int delta = 1) = 0;
|
||||
|
@ -7,6 +7,7 @@ class IWindowMessage;
|
||||
|
||||
class IWindow : public IDisplayable {
|
||||
public:
|
||||
virtual ~IWindow() = 0 { }
|
||||
virtual void Repaint() = 0;
|
||||
virtual void SetParent(IWindow* parent) = 0;
|
||||
virtual void Show() = 0;
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
class IWindowGroup {
|
||||
public:
|
||||
virtual ~IWindowGroup() = 0 { }
|
||||
virtual bool AddWindow(IWindowPtr window) = 0;
|
||||
virtual bool RemoveWindow(IWindowPtr window) = 0;
|
||||
virtual size_t GetWindowCount() = 0;
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
class IWindowMessage {
|
||||
public:
|
||||
virtual ~IWindowMessage() = 0 { }
|
||||
virtual IWindow* Target() = 0;
|
||||
virtual int MessageType() = 0;
|
||||
virtual int64 UserData1() = 0;
|
||||
|
@ -45,7 +45,7 @@ void Window::ProcessMessage(IWindowMessage &message) {
|
||||
}
|
||||
|
||||
bool Window::IsAcceptingMessages() {
|
||||
return this->IsVisible();
|
||||
return true; //this->IsVisible();
|
||||
}
|
||||
|
||||
bool Window::IsVisible() {
|
||||
@ -260,14 +260,16 @@ void Window::Clear() {
|
||||
}
|
||||
|
||||
void Window::Repaint() {
|
||||
if (this->frame && this->content) {
|
||||
wnoutrefresh(this->frame);
|
||||
if (this->isVisible) {
|
||||
if (this->frame && this->content) {
|
||||
wnoutrefresh(this->frame);
|
||||
|
||||
if (this->frame != this->content) {
|
||||
wnoutrefresh(this->content);
|
||||
if (this->frame != this->content) {
|
||||
wnoutrefresh(this->content);
|
||||
}
|
||||
|
||||
drawPending = true;
|
||||
}
|
||||
|
||||
drawPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user