Created a (temporary) musik::core::MessageQueue

Started on playlist functionality.
This commit is contained in:
Daniel Önnerby 2008-09-17 19:58:22 +00:00
parent 21e97a719b
commit 2c00c806f3
30 changed files with 820 additions and 66 deletions

View File

@ -180,6 +180,9 @@ utfstring Library::Base::GetDBPath(){
//////////////////////////////////////////
bool Library::Base::AddQuery( const Query::Base &query,unsigned int options ){
if(this->Exited()){
return false;
}
// Start by making a copy
Query::Ptr queryCopy( query.copy() );

93
src/core/MessageQueue.cpp Normal file
View File

@ -0,0 +1,93 @@
//////////////////////////////////////////////////////////////////////////////
//
// License Agreement:
//
// The following are Copyright © 2008, Daniel Önnerby
//
// 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 <core/MessageQueue.h>
//////////////////////////////////////////////////////////////////////////////
using namespace musik::core;
//////////////////////////////////////////////////////////////////////////////
MessageQueue MessageQueue::sInstance;
/*MessageQueue& MessageQueue::Instance(){
return MessageQueue::sInstance;
}*/
MessageQueue::MessageQueue(void)
{
}
MessageQueue::~MessageQueue(void)
{
}
MessageQueue::ControllerEventSignal& MessageQueue::EventController(){
return MessageQueue::sInstance.controllerEvent;
}
MessageQueue::EventSignal& MessageQueue::MessageEvent(const char* identifier){
return MessageQueue::sInstance.eventMap[identifier];
}
void MessageQueue::SendMessage(const char* identifier,void* data){
{
EventSignalMap::iterator eventSignal = MessageQueue::sInstance.eventMap.find(identifier);
if(eventSignal!=MessageQueue::sInstance.eventMap.end()){
// First call the controllers
MessageQueue::sInstance.controllerEvent(identifier,data);
}
}
{
// Just in case the controller would change the eventMap, lets find the eventSignal again.
EventSignalMap::iterator eventSignal = MessageQueue::sInstance.eventMap.find(identifier);
if(eventSignal!=MessageQueue::sInstance.eventMap.end()){
// Call the evenSignals
eventSignal->second(data);
}
}
}
MessageQueueData::MessageQueueData(){
}
MessageQueueData::~MessageQueueData(){
}

81
src/core/MessageQueue.h Normal file
View File

@ -0,0 +1,81 @@
//////////////////////////////////////////////////////////////////////////////
//
// License Agreement:
//
// The following are Copyright © 2008, Daniel Önnerby
//
// 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 <sigslot/sigslot.h>
#include <map>
#include <string>
//////////////////////////////////////////////////////////////////////////////
namespace musik { namespace core {
//////////////////////////////////////////////////////////////////////////////
struct MessageQueueData{
MessageQueueData();
virtual ~MessageQueueData();
};
class MessageQueue {
public:
typedef sigslot::signal2<const char*,void*> ControllerEventSignal;
typedef sigslot::signal1<void*> EventSignal;
static ControllerEventSignal& EventController();
static EventSignal& MessageEvent(const char* identifier);
static void SendMessage(const char* identifier,void* data=NULL);
private:
~MessageQueue();
MessageQueue();
//static MessageQueue& Instance();
private:
// The one and only instance
static MessageQueue sInstance;
typedef std::map<std::string,EventSignal> EventSignalMap;
EventSignalMap eventMap;
ControllerEventSignal controllerEvent;
};
//////////////////////////////////////////////////////////////////////////////
} } // musik::core
//////////////////////////////////////////////////////////////////////////////

View File

@ -55,14 +55,15 @@ Query::PlaylistSave::PlaylistSave(void){
Query::PlaylistSave::~PlaylistSave(void){
}
void Query::PlaylistSave::SavePlaylist(int playlistId,utfstring playlistName,musik::core::tracklist::IRandomAccess &tracklist){
void Query::PlaylistSave::SavePlaylist(const utfstring playlistName,int playlistId,musik::core::tracklist::IRandomAccess *tracklist){
this->playlistId = playlistId;
this->playlistName = playlistName;
for(int i(0);i<tracklist.Size();++i){
musik::core::TrackPtr track=tracklist[i];
if(track){
this->tracks.push_back(track->id);
this->tracks.clear();
if(tracklist){
for(int i(0);i<tracklist->Size();++i){
this->tracks.push_back((*tracklist)[i]->id);
}
}
}
@ -72,11 +73,13 @@ bool Query::PlaylistSave::ParseQuery(Library::Base *library,db::Connection &db){
db::ScopedTransaction transaction(db);
{
db::Statement updatePlaylist("INSERT OR REPLACE INT playlists (id,name) VALUES (?,?)",db);
if(this->playlistId==0){
db::Statement updatePlaylist("INSERT OR REPLACE INTO playlists (id,name,user_id) VALUES (?,?,?)",db);
if(this->playlistId!=0){
updatePlaylist.BindInt(0,this->playlistId);
}
updatePlaylist.BindTextUTF(1,this->playlistName);
updatePlaylist.BindInt(2,library->userId);
if( updatePlaylist.Step()==db::Done ){
if(this->playlistId==0){
this->playlistId = db.LastInsertedId();
@ -114,12 +117,18 @@ Query::Ptr Query::PlaylistSave::copy() const{
}
bool Query::PlaylistSave::RunCallbacks(Library::Base *library){
bool callCallbacks(false);
{
boost::mutex::scoped_lock lock(library->libraryMutex);
if( (this->status & Status::Ended)!=0){
this->PlaylistSaved(this->playlistId);
return true;
callCallbacks = true;
}
return false;
}
if(callCallbacks){
this->PlaylistSaved(this->playlistId);
}
return callCallbacks;
}

View File

@ -64,7 +64,7 @@ namespace musik{ namespace core{
PlaylistSave(void);
~PlaylistSave(void);
void SavePlaylist(int playlistId,utfstring playlistName,musik::core::tracklist::IRandomAccess &tracklist);
void SavePlaylist(const utfstring playlistName,int playlistId=0,musik::core::tracklist::IRandomAccess *tracklist=NULL);
sigslot::signal1<int> PlaylistSaved;

View File

@ -61,6 +61,8 @@ bool Query::Playlists::ParseQuery(Library::Base *library,db::Connection &db){
db::Statement stmt("SELECT id,name FROM playlists WHERE user_id=?",db);
stmt.BindInt(0,library->userId);
while(stmt.Step()==db::Row){
tracklist::Ptr playlist( new tracklist::Playlist(
stmt.ColumnInt(0),

View File

@ -212,6 +212,14 @@
RelativePath=".\Crypt.h"
>
</File>
<File
RelativePath=".\MessageQueue.cpp"
>
</File>
<File
RelativePath=".\MessageQueue.h"
>
</File>
<File
RelativePath=".\Preferences.cpp"
>

View File

@ -272,7 +272,7 @@ void Connection::WriteThread(){
this->waitCondition.wait(lock);
}
if(!this->outgoingQueries.empty()){
if(!this->outgoingQueries.empty() && !this->exit){
sendQuery = this->outgoingQueries.front();
}
}
@ -329,12 +329,12 @@ void Connection::Exit(){
{
boost::mutex::scoped_lock lock(this->libraryMutex);
if(!this->exit){
this->exit = true;
if(this->socket.is_open()){
this->socket.close();
}
this->server->RemoveUserSession(this->userSession);
}
this->exit = true;
}
this->waitCondition.notify_all();
this->authCondition.notify_all();

View File

@ -48,6 +48,7 @@ using namespace musik::core::tracklist;
Playlist::Playlist(int id,utfstring name,musik::core::LibraryPtr library)
:Standard()
,id(0)
,name(name)
{
this->SetLibrary(library);

View File

@ -174,7 +174,7 @@ void Writer::Send(){
try{
// Time to send the buffer
if(!sendBuffer.empty()){
if(!sendBuffer.empty() && this->socket->is_open()){
boost::asio::write(*(this->socket),boost::asio::buffer(sendBuffer));
// Log
//std::ofstream logFile("mc2_Writer.log",std::ios::app);

View File

@ -40,6 +40,7 @@
#include <cube/LibraryWindowController.hpp>
#include <cube/LibraryWindowView.hpp>
#include <cube/SourcesView.hpp>
#include <cube/SourcesController.hpp>
#include <core/LibraryFactory.h>
#include <core/Pluginfactory.h>
@ -79,6 +80,8 @@ void LibraryWindowController::OnViewCreated(Window* window)
this->UpdateLibraryTabs();
LibraryFactory::Instance().LibrariesUpdated.connect(this,&LibraryWindowController::UpdateLibraryTabs);
// Connect to the MessageQueue
musik::core::MessageQueue::EventController().connect(this,&LibraryWindowController::OnLibraryMessage);
}
void LibraryWindowController::UpdateLibraryTabs(){
@ -95,15 +98,15 @@ void LibraryWindowController::UpdateLibraryTabs(){
// check if library already exist
bool found(false);
for(LibraryWindowVector::iterator libraryWindow=this->libraries.begin();libraryWindow!=this->libraries.end() && !found;++libraryWindow){
if( (*libraryWindow)->library->Identifier()==libraryId ){
for(SourcesMap::iterator libraryWindow=this->libraries.begin();libraryWindow!=this->libraries.end() && !found;++libraryWindow){
if( libraryWindow->second->library->Identifier()==libraryId ){
found = true;
}
}
if(!found){
SourcesView* sourcesView = new SourcesView();
this->libraries.push_back(SourcesControllerPtr(new SourcesController(*sourcesView,*library)));
this->libraries[sourcesView] = SourcesControllerPtr(new SourcesController(*sourcesView,*library));
this->view.AddTab( (*library)->Identifier() ,sourcesView);
}
@ -115,3 +118,23 @@ void LibraryWindowController::OnResize(Window* window, Size size)
RedrawLock redrawLock(&this->view);
// this->clientView->Resize(this->mainWindow.ClientSize());
}
SourcesController* LibraryWindowController::CurrentSourceController(){
SourcesView *sourcesView = (SourcesView*)this->view.ActiveWindow();
SourcesMap::iterator foundLibrary = this->libraries.find(sourcesView);
if(foundLibrary!=this->libraries.end()){
return foundLibrary->second.get();
}
return NULL;
}
void LibraryWindowController::OnLibraryMessage(const char* identifier,void* data){
if(!data){
SourcesController* sourcesController = this->CurrentSourceController();
if(sourcesController){
musik::core::MessageQueue::SendMessage(identifier,sourcesController->library.get());
}
}
}

View File

@ -48,11 +48,13 @@ namespace win32cpp{
}
namespace musik { namespace cube {
class LibraryWindowView;
class SourcesView;
class SourcesController;
} }
//////////////////////////////////////////////////////////////////////////////
#include <core/Library/Base.h>
#include <cube/SourcesController.hpp>
#include <core/MessageQueue.h>
#include <win32cpp/Timer.hpp>
#include <win32cpp/Types.hpp>
@ -69,23 +71,27 @@ namespace musik { namespace cube {
class LibraryWindowController : public EventHandler
{
public: /*ctor*/ LibraryWindowController(LibraryWindowView& view);
public: /*dtor*/ ~LibraryWindowController();
public:
LibraryWindowController(LibraryWindowView& view);
~LibraryWindowController();
protected:
protected:
void OnViewCreated(Window* window);
void OnResize(Window* window, Size size);
void UpdateLibraryTabs();
void OnLibraryMessage(const char* identifier,void* data);
LibraryWindowView& view;
// SourcesController* sourcesController;
typedef boost::shared_ptr<SourcesController> SourcesControllerPtr;
typedef std::vector<SourcesControllerPtr> LibraryWindowVector;
typedef std::map<SourcesView*,SourcesControllerPtr> SourcesMap;
LibraryWindowVector libraries;
SourcesMap libraries;
public:
SourcesController* CurrentSourceController();
};

View File

@ -38,12 +38,14 @@
#include "pch.hpp"
#include <core/LibraryFactory.h>
#include <core/MessageQueue.h>
#include <cube/MainMenuController.hpp>
#include <cube/dialog/AddLibraryController.hpp>
#include <win32cpp/Application.hpp>
#include <win32cpp/TopLevelWindow.hpp>
#include <boost/format.hpp>
//////////////////////////////////////////////////////////////////////////////
using namespace musik::cube;
@ -140,6 +142,7 @@ void MainMenuController::OnHelpAbout(MenuItemRef menuItem)
}
void MainMenuController::OnNewPlaylist(MenuItemRef menuItem){
musik::core::MessageQueue::SendMessage("NewPlaylist");
}

View File

@ -75,7 +75,16 @@ SourcesItemRef SourcesCategory::Add(SourcesItemRef item)
return item;
}
SourcesItemRef SourcesCategory::Remove(SourcesItemRef item)
void SourcesCategory::Remove(SourcesItemRef item)
{
throw NotImplementedException();
for(SourcesItemList::iterator it=this->items.begin();it!=this->items.end();){
if(item==*it){
it = this->items.erase(it);
}else{
++it;
}
}
this->CountChanged((int) this->items.size());
//throw NotImplementedException();
}

View File

@ -66,7 +66,7 @@ public: uistring Caption() const;
public: int Count() const;
public: SourcesItemRef ItemAt(int index) const;
public: SourcesItemRef Add(SourcesItemRef item);
public: SourcesItemRef Remove(SourcesItemRef item);
public: void Remove(SourcesItemRef item);
private: typedef std::vector<SourcesItemRef> SourcesItemList;
private: uistring caption;

View File

@ -39,6 +39,10 @@
#include <cube/SourcesController.hpp>
#include <cube/SourcesListModel.hpp>
#include <cube/SourcesView.hpp>
#include <cube/dialog/NewPlaylistController.hpp>
#include <core/MessageQueue.h>
#include <core/Query/Playlists.h>
//////////////////////////////////////////////////////////////////////////////
@ -68,6 +72,8 @@ using namespace musik::cube;
library->OnQueryQueueStart.connect(this,&SourcesController::QueryQueueStart);
library->OnQueryQueueEnd.connect(this,&SourcesController::QueryQueueEnd);
musik::core::MessageQueue::MessageEvent("NewPlaylist").connect(this,&SourcesController::OnNewPlaylist);
}
void SourcesController::OnViewCreated(Window* window)
@ -75,6 +81,9 @@ void SourcesController::OnViewCreated(Window* window)
this->model.CategoryAdded.connect(this, &SourcesController::OnModelCategoryAdded);
this->model.CategoryRemoved.connect(this, &SourcesController::OnModelCategoryRemoved);
this->model.Load();
this->UpdatePlaylists();
}
void SourcesController::OnModelCategoryAdded(CategoryRef category)
@ -118,6 +127,32 @@ void SourcesController::QueryQueueLoop(){
this->library->RunCallbacks();
}
void SourcesController::OnNewPlaylist(void* data){
if(data==this->library.get()){
win32cpp::TopLevelWindow popupDialog(_(_T("New Playlist")));
popupDialog.SetMinimumSize(Size(300, 150));
dialog::NewPlaylistController newPlaylist(popupDialog,this->library);
popupDialog.ShowModal(TopLevelWindow::FindFromAncestor(&this->view));
this->UpdatePlaylists();
}
}
void SourcesController::UpdatePlaylists(){
musik::core::Query::Playlists playlistQuery;
playlistQuery.PlaylistList.connect(this,&SourcesController::OnPlaylists);
this->library->AddQuery(playlistQuery);
}
void SourcesController::OnPlaylists(std::vector<musik::core::tracklist::Ptr> trackLists){
this->model.OnPlaylists(trackLists);
this->listController->sourcesListModel->Update();
// this->view.Redraw();
}
//////////////////////////////////////////////////////////////////////////////
// SourcesController::ListController
//////////////////////////////////////////////////////////////////////////////

View File

@ -77,6 +77,7 @@ private:
void OnActiveItemChanged(ItemRef newItem);
void OnModelCategoryAdded(CategoryRef category);
void OnModelCategoryRemoved(CategoryRef category);
void OnNewPlaylist(void* data);
protected:
SourcesView& view;
@ -87,6 +88,9 @@ protected:
void QueryQueueStart();
void QueryQueueEnd();
void QueryQueueLoop();
void UpdatePlaylists();
void OnPlaylists(std::vector<musik::core::tracklist::Ptr> trackLists);
};
//////////////////////////////////////////////////////////////////////////////
@ -104,7 +108,9 @@ private: void OnListCreated(Window* window);
private: void OnListSelectionChanged(ListView* listView);
private: ListView& listView;
private: ListModelRef sourcesListModel;
private:
friend class SourcesController;
ListModelRef sourcesListModel;
};
//////////////////////////////////////////////////////////////////////////////

View File

@ -172,6 +172,12 @@ CategoryRef SourcesListModel::RemoveCategory(CategoryRef category)
throw InvalidSourcesCategoryException();
}
void SourcesListModel::Update(){
this->IndexCategories();
this->SetRowCount(this->VisibleItemCount());
}
void SourcesListModel::IndexCategories()
{
this->categoryIndexMap.clear();

View File

@ -81,6 +81,7 @@ public: /*ctor*/ SourcesListModel();
public: CategoryRef AddCategory(CategoryRef category);
public: CategoryRef RemoveCategory(CategoryRef category);
public: void SelectedRowChanged(int newIndex);
public: void Update();
// private API
private: int VisibleItemCount();

View File

@ -45,6 +45,8 @@
#include <cube/TracklistView.hpp>
#include <cube/TracklistController.hpp>
#include <core/tracklist/Playlist.h>
#include <win32cpp/Label.hpp>
using namespace musik::cube;
@ -116,7 +118,7 @@ class NowPlayingItem: public SourcesItem
private:
/*ctor*/ NowPlayingItem(musik::core::LibraryPtr library)
: controller(view,NULL,library->NowPlaying())
: controller(view,NULL,library->NowPlaying(),TracklistController::HighlightActive|TracklistController::Deletable)
{
}
@ -139,6 +141,39 @@ private: TracklistView view;
private: TracklistController controller;
};
//////////////////////////////////////////////////////////////////////////////
class PlaylistItem: public SourcesItem
{
private:
/*ctor*/ PlaylistItem(musik::core::tracklist::Ptr playlist)
: controller(view,NULL,playlist,TracklistController::HighlightActive|TracklistController::Deletable)
{
}
public: /*dtor*/ ~PlaylistItem()
{
}
public: static SourcesItemRef Create(musik::core::tracklist::Ptr playlist)
{
return SourcesItemRef(new PlaylistItem(playlist));
}
public: virtual uistring Caption() {
musik::core::tracklist::Playlist* playlist = (musik::core::tracklist::Playlist*)(this->controller.Tracklist().get());
return playlist->Name();
}
public: virtual Window* View()
{
return &this->view;
}
private: TracklistView view;
private: TracklistController controller;
};
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
#include <cube/SettingsView.hpp>
@ -221,3 +256,26 @@ void SourcesModel::RemoveCategory(CategoryRef category)
this->categories.erase(it);
this->CategoryRemoved(category);
}
void SourcesModel::OnPlaylists(SourcesModel::PlaylistVector &playlists){
// Start by removing the old ones
for(PlaylistItemMap::iterator it=this->playlistItemsMap.begin();it!=this->playlistItemsMap.end();++it){
// Remove the item from the category
this->playlistCategory->Remove(it->second);
}
// Clear the map
this->playlistItemsMap.clear();
// Start creating the new playlists
for(SourcesModel::PlaylistVector::iterator playlist=playlists.begin();playlist!=playlists.end();++playlist){
// Create the sourcesItem
SourcesItemRef sourceItem = PlaylistItem::Create(*playlist);
playlistCategory->Add(sourceItem);
this->playlistItemsMap[*playlist] = sourceItem;
}
}

View File

@ -40,8 +40,10 @@
#include <cube/SourcesListModel.hpp>
#include <core/Library/Base.h>
#include <core/Track.h>
#include <vector>
#include <map>
//////////////////////////////////////////////////////////////////////////////
@ -49,30 +51,50 @@ using namespace win32cpp;
namespace musik { namespace cube {
// Forward
class SourcesController;
//////////////////////////////////////////////////////////////////////////////
class SourcesModel
{
public: typedef SourcesItemRef ItemRef;
public: typedef SourcesCategoryRef CategoryRef;
private: typedef std::vector<CategoryRef> CategoryList;
private: class InvalidCategoryException: public Exception { };
public:
typedef SourcesItemRef ItemRef;
typedef SourcesCategoryRef CategoryRef;
private:
typedef std::vector<CategoryRef> CategoryList;
public: sigslot::signal1<CategoryRef> CategoryAdded;
public: sigslot::signal1<CategoryRef> CategoryRemoved;
class InvalidCategoryException: public Exception { };
public: /*ctor*/ SourcesModel(musik::core::LibraryPtr library);
sigslot::signal1<CategoryRef> CategoryAdded;
sigslot::signal1<CategoryRef> CategoryRemoved;
public:
/*ctor*/ SourcesModel(musik::core::LibraryPtr library);
musik::core::LibraryPtr library;
public: void Load();
public:
void Load();
protected: void AddCategory(CategoryRef category);
protected: void RemoveCategory(CategoryRef category);
protected: void OnActiveItemChanged(ItemRef);
protected:
void AddCategory(CategoryRef category);
void RemoveCategory(CategoryRef category);
void OnActiveItemChanged(ItemRef);
typedef std::vector<musik::core::tracklist::Ptr> PlaylistVector;
typedef std::map<musik::core::tracklist::Ptr,SourcesItemRef> PlaylistItemMap;
PlaylistItemMap playlistItemsMap;
private:
ItemRef activeItem;
CategoryList categories;
CategoryRef playlistCategory;
protected:
friend class SourcesController;
void OnPlaylists(PlaylistVector &playlists);
private: ItemRef activeItem;
private: CategoryList categories;
private: CategoryRef playlistCategory;
};
//////////////////////////////////////////////////////////////////////////////

View File

@ -55,9 +55,11 @@ using namespace musik::cube;
/*ctor*/ TracklistController::TracklistController(
TracklistView& view,
musik::core::Query::ListBase *connectedQuery,
musik::core::tracklist::Ptr tracklist)
musik::core::tracklist::Ptr tracklist,
unsigned int options)
: view(view)
, model(new TracklistModel(connectedQuery, tracklist))
, model(new TracklistModel(connectedQuery, tracklist,options))
, options(options)
{
this->view.Handle()
? this->OnViewCreated(&view)
@ -72,6 +74,15 @@ using namespace musik::cube;
}
musik::core::tracklist::Ptr TracklistController::Tracklist(){
TracklistModel* model = (TracklistModel*)this->model.get();
if(model){
return model->tracklist;
}
return musik::core::tracklist::Ptr();
}
void TracklistController::OnViewCreated(Window* window)
{
typedef ListView::Column Column;

View File

@ -65,6 +65,11 @@ namespace musik { namespace cube {
class TracklistController : public EventHandler
{
public:
enum Options:unsigned int{
HighlightActive=1,
Deletable=2
};
private:
typedef ListView::ColumnRef ColumnRef;
typedef std::vector<ColumnRef> ColumnList;
@ -74,7 +79,10 @@ public:
/*ctor*/ TracklistController(
TracklistView& listView,
musik::core::Query::ListBase *connectedQuery,
musik::core::tracklist::Ptr tracklist);
musik::core::tracklist::Ptr tracklist,
unsigned int options=0);
musik::core::tracklist::Ptr Tracklist();
private:
void OnViewCreated(Window* window);
@ -91,6 +99,7 @@ private:
ColumnList columns;
win32cpp::MenuRef contextMenu;
musik::core::Query::SortTracks sortQuery;
unsigned int options;
};

View File

@ -43,6 +43,7 @@
#include "pch.hpp"
#include <cube/TracklistModel.hpp>
#include <cube/TracklistColumn.hpp>
#include <cube/TracklistController.hpp>
#include <win32cpp/Utility.hpp>
#include <win32cpp/ApplicationThread.hpp>
@ -58,8 +59,9 @@ using namespace musik::cube;
//////////////////////////////////////////////////////////////////////////////
/*ctor*/ TracklistModel::TracklistModel(musik::core::Query::ListBase *connectedQuery,musik::core::tracklist::Ptr setTracklist)
/*ctor*/ TracklistModel::TracklistModel(musik::core::Query::ListBase *connectedQuery,musik::core::tracklist::Ptr setTracklist,unsigned int options)
: currentPosition(-1)
, options(options)
{
this->tracklist = setTracklist;
@ -103,7 +105,7 @@ uistring TracklistModel::CellValueToString(int rowIndex, ColumnRef co
return win32cpp::Escape(result);
break;
}
if(rowIndex==this->currentPosition){
if(rowIndex==this->currentPosition && this->options&TracklistController::HighlightActive){
return win32cpp::Escape(value)+_T("***");
}
return win32cpp::Escape(value);

View File

@ -68,7 +68,8 @@ public:
// public API
TracklistModel(
musik::core::Query::ListBase *connectedQuery,
musik::core::tracklist::Ptr setTracklist);
musik::core::tracklist::Ptr setTracklist,
unsigned int options);
void ConnectToQuery(musik::core::Query::ListBase *connectedQuery);
void OnRowActivated(int row);
@ -86,7 +87,7 @@ protected:
void OnPositionChanged(int activeRow,int oldActiveRow);
int currentPosition;
unsigned int options;
public:
musik::core::tracklist::Ptr tracklist; // FIXME: no public fields!

View File

@ -102,7 +102,7 @@
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="copy &quot;$(SolutionDir)\src\3rdparty\vld\*.*&quot; &quot;$(TargetDir)&quot;&#x0D;&#x0A;xcopy /y /s &quot;$(SolutionDir)\data&quot; &quot;$(TargetDir)&quot;"
CommandLine="copy &quot;$(SolutionDir)\src\3rdparty\vld\*.*&quot; &quot;$(TargetDir)&quot;&#x0D;&#x0A;xcopy /y /s &quot;$(SolutionDir)\data&quot; &quot;$(TargetDir)&quot;&#x0D;&#x0A;"
/>
</Configuration>
<Configuration
@ -473,6 +473,26 @@
>
</File>
</Filter>
<Filter
Name="NewPlaylist"
>
<File
RelativePath=".\dialog\NewPlaylistController.cpp"
>
</File>
<File
RelativePath=".\dialog\NewPlaylistController.hpp"
>
</File>
<File
RelativePath=".\dialog\NewPlaylistView.cpp"
>
</File>
<File
RelativePath=".\dialog\NewPlaylistView.hpp"
>
</File>
</Filter>
</Filter>
<File
RelativePath=".\main.cpp"

View File

@ -0,0 +1,89 @@
//////////////////////////////////////////////////////////////////////////////
//
// License Agreement:
//
// The following are Copyright © 2007, mC2 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 <cube/dialog/NewPlaylistController.hpp>
#include <core/Library/Base.h>
#include <core/Query/PlaylistSave.h>
#include <core/MessageQueue.h>
#include <win32cpp/Window.hpp>
#include <win32cpp/Button.hpp>
#include <win32cpp/EditView.hpp>
//////////////////////////////////////////////////////////////////////////////
using namespace musik::cube::dialog;
using namespace win32cpp;
//////////////////////////////////////////////////////////////////////////////
NewPlaylistController::NewPlaylistController(win32cpp::TopLevelWindow &mainWindow,musik::core::LibraryPtr library)
:mainWindow(mainWindow)
,library(library)
{
this->view = new NewPlaylistView();
this->mainWindow.AddChild(this->view);
this->view->Handle()
? this->OnViewCreated(this->view)
: this->view->Created.connect(this, &NewPlaylistController::OnViewCreated);
}
NewPlaylistController::~NewPlaylistController(){
}
void NewPlaylistController::OnViewCreated(Window* window)
{
this->view->cancelButton->Pressed.connect(this,&NewPlaylistController::OnCancel);
this->view->okButton->Pressed.connect(this,&NewPlaylistController::OnOK);
}
void NewPlaylistController::OnCancel(win32cpp::Button* button){
this->mainWindow.Close();
}
void NewPlaylistController::OnOK(win32cpp::Button* button){
musik::core::Query::PlaylistSave savePlaylistQuery;
savePlaylistQuery.SavePlaylist( this->view->name->Caption() );
this->library->AddQuery(savePlaylistQuery,musik::core::Query::UnCanceable);
this->mainWindow.Close();
}

View File

@ -0,0 +1,79 @@
//////////////////////////////////////////////////////////////////////////////
//
// License Agreement:
//
// The following are Copyright © 2007, mC2 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
//////////////////////////////////////////////////////////////////////////////
// Forward declare
namespace win32cpp{
class Window;
class Button;
}
//////////////////////////////////////////////////////////////////////////////
#include <win32cpp/Types.hpp>
#include <win32cpp/TopLevelWindow.hpp>
#include <cube/dialog/NewPlaylistView.hpp>
#include <core/Library/Base.h>
//////////////////////////////////////////////////////////////////////////////
namespace musik { namespace cube { namespace dialog{
//////////////////////////////////////////////////////////////////////////////
class NewPlaylistController : public win32cpp::EventHandler{
public:
NewPlaylistController(win32cpp::TopLevelWindow &mainWindow,musik::core::LibraryPtr library);
~NewPlaylistController();
private:
void OnViewCreated(win32cpp::Window* window);
void OnCancel(win32cpp::Button* button);
void OnOK(win32cpp::Button* button);
win32cpp::TopLevelWindow &mainWindow;
NewPlaylistView *view;
musik::core::LibraryPtr library;
};
//////////////////////////////////////////////////////////////////////////////
} } } // musik::cube::dialog

View File

@ -0,0 +1,108 @@
//////////////////////////////////////////////////////////////////////////////
//
// License Agreement:
//
// The following are Copyright © 2007, mC2 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 <cube/dialog/NewPlaylistView.hpp>
#include <core/Library/Base.h>
#include <win32cpp/Label.hpp>
#include <win32cpp/Button.hpp>
#include <win32cpp/LinearLayout.hpp>
#include <win32cpp/BarLayout.hpp>
#include <win32cpp/EditView.hpp>
//////////////////////////////////////////////////////////////////////////////
using namespace musik::cube::dialog;
using namespace win32cpp;
//////////////////////////////////////////////////////////////////////////////
NewPlaylistView::NewPlaylistView()
: Frame(NULL,FramePadding(6))
{
}
void NewPlaylistView::OnCreated()
{
FontRef boldFont(Font::Create());
boldFont->SetBold(true);
// Top Row layout
LinearLayout* topRowLayout = new LinearLayout(LinearRowLayout);
topRowLayout->SetDefaultChildFill(false);
topRowLayout->SetDefaultChildAlignment(win32cpp::ChildAlignMiddle);
Label *label;
Size labelSize(80,0);
// First rows column layout
LinearLayout* firstColumnLayout = new LinearLayout(LinearColumnLayout);
firstColumnLayout->SetDefaultChildFill(false);
firstColumnLayout->SetDefaultChildAlignment(win32cpp::ChildAlignCenter);
label = firstColumnLayout->AddChild(new Label(_T("New Playlist")));
label->SetFont(boldFont);
topRowLayout->AddChild(firstColumnLayout);
// Second rows column layout
LinearLayout* secondColumnLayout = new LinearLayout(LinearColumnLayout);
secondColumnLayout->SetDefaultChildAlignment(win32cpp::ChildAlignTop);
label = secondColumnLayout->AddChild(new Label(_T("Name:") ));
label->Resize(labelSize);
this->name = secondColumnLayout->AddChild(new EditView(160,20 ));
topRowLayout->AddChild(secondColumnLayout);
// Last rows column layout
LinearLayout* bottomButtonLayout = new LinearLayout(LinearColumnLayout);
bottomButtonLayout->SetDefaultChildFill(false);
this->cancelButton = bottomButtonLayout->AddChild(new Button(_T("Cancel")));
this->okButton = bottomButtonLayout->AddChild(new Button(_T("OK")));
this->cancelButton->Resize(60,20);
this->okButton->Resize(60,20);
topRowLayout->AddChild(bottomButtonLayout);
topRowLayout->SetChildAlignment(bottomButtonLayout,ChildAlignRight);
this->AddChild(topRowLayout);
}

View File

@ -0,0 +1,69 @@
//////////////////////////////////////////////////////////////////////////////
//
// License Agreement:
//
// The following are Copyright © 2007, mC2 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
//////////////////////////////////////////////////////////////////////////////
// Forward declare
namespace win32cpp{
class Button;
class EditView;
}
//////////////////////////////////////////////////////////////////////////////
#include <win32cpp/Frame.hpp>
//////////////////////////////////////////////////////////////////////////////
namespace musik { namespace cube { namespace dialog {
//////////////////////////////////////////////////////////////////////////////
// forward
//////////////////////////////////////////////////////////////////////////////
class NewPlaylistView: public win32cpp::Frame{
public:
NewPlaylistView();
virtual void OnCreated();
win32cpp::Button *okButton, *cancelButton;
win32cpp::EditView *name;
};
//////////////////////////////////////////////////////////////////////////////
} } } // musik::cube::dialog