- Query::ListSelection and Query::TrackMetadata are fully working with Library::Remote.

- Fixed a tracklist issue where the tracklist where sending 1 query for each track.
- Threading issues fixed in Library::Remote and server::Connection.
This commit is contained in:
Daniel Önnerby 2008-08-19 11:28:38 +00:00
parent 621afdf5cc
commit c12a02487b
20 changed files with 431 additions and 102 deletions

View File

@ -141,7 +141,7 @@ utfstring musik::core::GetPath(const utfstring &sFile){
///\returns
///Converted string
//////////////////////////////////////////
std::string musik::core::ConvertUTF8(std::wstring &sString){
std::string musik::core::ConvertUTF8(const std::wstring &sString){
std::string sUTF8;
utf8::utf16to8(sString.begin(),sString.end(),std::back_inserter(sUTF8));
return sUTF8;
@ -157,7 +157,7 @@ std::string musik::core::ConvertUTF8(std::wstring &sString){
///\returns
///Converted string
//////////////////////////////////////////
std::wstring musik::core::ConvertUTF16(std::string &sString){
std::wstring musik::core::ConvertUTF16(const std::string &sString){
std::wstring sUTF16;
utf8::utf8to16(sString.begin(),sString.end(),std::back_inserter(sUTF16));
return sUTF16;

View File

@ -61,8 +61,8 @@ namespace musik{ namespace core{
*****************************/
utfstring GetPluginDirectory();
std::string ConvertUTF8(std::wstring &sString);
std::wstring ConvertUTF16(std::string &sString);
std::string ConvertUTF8(const std::wstring &sString);
std::wstring ConvertUTF16(const std::string &sString);
std::wstring ConvertUTF16(const char *string);
UINT64 Checksum(char *data,unsigned int bytes);

View File

@ -144,6 +144,7 @@ utfstring Library::Base::GetDBPath(){
/// - Query::Options::CancelQueue : Cancel all other queries that are to be executed by the Library.
/// - Query::Options::CancelSimilar : Cancel all similar queries. A similar query is a query that originates from the same Query::Base that is passed to the AddQuery.
/// - Query::Options::UnCanceable : Under no circumstances is this Query allowed to be canceled.
/// - Query::Options::UnCanceable : Under no circumstances is this Query allowed to be canceled.
///
///The query will be copied by the library and executed in the library thread.
///
@ -159,6 +160,11 @@ bool Library::Base::AddQuery( const Query::Base &query,unsigned int options ){
// Start by making a copy
Query::Ptr queryCopy( query.copy() );
//
if(options&Query::CopyUniqueId){
queryCopy->uniqueId = query.uniqueId;
}
queryCopy->PreAddQuery(this);
// Since query is not added to queue yet, variables can now be changed without locking.

View File

@ -125,9 +125,12 @@ void Library::Remote::ReadThread(){
boost::system::error_code error = boost::asio::error::host_not_found;
while (error && endpointIterator!=end){
this->socket.close();
this->socket.connect(*endpointIterator++, error);
this->socket.connect(*endpointIterator, error);
if(error){
endpointIterator++;
}
}
if (error){
if (error || endpointIterator==end){
this->Exit();
return;
}
@ -159,6 +162,7 @@ void Library::Remote::ReadThread(){
if(node.Name()=="queryresults"){
unsigned int queryId = boost::lexical_cast<unsigned int>(node.Attributes()["id"]);
unsigned int uniqueId = boost::lexical_cast<unsigned int>(node.Attributes()["uid"]);
Query::Ptr currentQuery;
// This is a query node
// Find the query in the outgoingQueries list
@ -166,15 +170,17 @@ void Library::Remote::ReadThread(){
boost::mutex::scoped_lock lock(this->libraryMutex);
// Reverse loop since it's most likely the query is in the end
for(QueryList::reverse_iterator query=this->outgoingQueries.rbegin();query!=this->outgoingQueries.rend();++query){
if( (*query)->queryId==queryId ){
if( (*query)->uniqueId==uniqueId ){
currentQuery = *query;
}
}
}
if(currentQuery){
if(currentQuery->RecieveResults(node,this)){
boost::mutex::scoped_lock lock(this->libraryMutex);
currentQuery->status |= Query::Base::Status::Ended;
}else{
boost::mutex::scoped_lock lock(this->libraryMutex);
currentQuery->status |= Query::Base::Status::Canceled | Query::Base::Status::Ended;
}
}
@ -214,7 +220,7 @@ void Library::Remote::WriteThread(){
this->outgoingQueries.push_back(query);
// Set query as started
// query->status |= Query::Base::Status::Started;
query->status |= Query::Base::Status::Started;
}
////////////////////////////////////////////////////////////
@ -222,6 +228,7 @@ void Library::Remote::WriteThread(){
xml::WriterNode queryNode(rootNode,"query");
queryNode.Attributes()["type"] = query->Name();
queryNode.Attributes()["id"] = boost::lexical_cast<std::string>(query->queryId);
queryNode.Attributes()["uid"] = boost::lexical_cast<std::string>(query->uniqueId);
if(query->options){
queryNode.Attributes()["options"] = boost::lexical_cast<std::string>(query->options);
@ -233,6 +240,10 @@ void Library::Remote::WriteThread(){
query->status |= Query::Base::Status::Canceled | Query::Base::Status::Ended;
}
////////////////////////////////////////////////////////////
// Notify that the Query is finished.
this->waitCondition.notify_all();
// Check if writer has quit
if(writer.Exited()){
this->Exit();
@ -265,3 +276,15 @@ void Library::Remote::CancelCurrentQuery( ){
}
void Library::Remote::Exit(){
{
boost::mutex::scoped_lock lock(this->libraryMutex);
if(!this->exit){
if(this->socket.is_open()){
this->socket.close();
}
}
this->exit = true;
}
this->waitCondition.notify_all();
}

View File

@ -70,6 +70,7 @@ class Remote : public Library::Base{
protected:
void CancelCurrentQuery( );
virtual void Exit();
private:
// Methods:

View File

@ -38,18 +38,22 @@
#include <core/Query/Base.h>
#include <core/Library/Base.h>
#include <core/xml/ParserNode.h>
#include <core/xml/WriterNode.h>
using namespace musik::core;
Query::Base::Base(void)
:status(0)
,options(0)
,uniqueId(0)
{
// This will guarantee that the query id is uniq for each query, but copies will not.
// This is usefull when canceling similar queries
static unsigned int uniqueQueryId(0);
uniqueQueryId++;
this->queryId = uniqueQueryId;
this->queryId = uniqueQueryId;
}
Query::Base::~Base(void){
@ -114,3 +118,10 @@ bool Query::Base::SendResults(musik::core::xml::WriterNode &queryNode,Library::B
std::string Query::Base::Name(){
return "Unknown";
}
void Query::Base::PostCopy(){
static unsigned int uniqueQueryId(0);
uniqueQueryId++;
this->uniqueId = uniqueQueryId;
}

View File

@ -50,6 +50,10 @@ namespace musik{ namespace core{
namespace server{
class Connection;
}
namespace xml{
class ParserNode;
class WriterNode;
}
} }
//////////////////////////////////////////////////////////////////////////////
@ -57,8 +61,6 @@ namespace musik{ namespace core{
#include <sigslot/sigslot.h>
#include <boost/shared_ptr.hpp>
#include <core/xml/ParserNode.h>
#include <core/xml/WriterNode.h>
//////////////////////////////////////////////////////////////////////////////
@ -74,7 +76,8 @@ enum Options:unsigned int{
Prioritize = 4,
CancelQueue = 8,
CancelSimilar = 16,
UnCanceable = 32
UnCanceable = 32,
CopyUniqueId = 64
};
//////////////////////////////////////////
@ -122,6 +125,7 @@ class Base : public sigslot::has_slots<> {
///Used for comparing queries and find similar queries.
//////////////////////////////////////////
unsigned int queryId;
unsigned int uniqueId;
//////////////////////////////////////////
///\brief
@ -205,6 +209,9 @@ class Base : public sigslot::has_slots<> {
virtual bool SendQuery(musik::core::xml::WriterNode &queryNode);
virtual bool RecieveResults(musik::core::xml::ParserNode &queryNode,Library::Base *library);
virtual bool SendResults(musik::core::xml::WriterNode &queryNode,Library::Base *library);
public:
void PostCopy();
};

View File

@ -38,6 +38,8 @@
#include <core/Query/ListBase.h>
#include <core/Library/Base.h>
#include <core/Common.h>
#include <core/xml/ParserNode.h>
#include <core/xml/WriterNode.h>
#include <boost/algorithm/string.hpp>
using namespace musik::core;
@ -384,4 +386,54 @@ void Query::ListBase::DummySlotTrackInfo(UINT64,UINT64,UINT64){
}
bool Query::ListBase::RecieveQueryStandardNodes(musik::core::xml::ParserNode &node){
if(node.Name()=="listeners"){
// Wait for all content
node.WaitForContent();
// Secondly, lets look for what to query for
// Split comaseparated list
typedef std::vector<std::string> StringVector;
StringVector keys;
boost::algorithm::split(keys,node.Content(),boost::algorithm::is_any_of(","));
for(StringVector::iterator key=keys.begin();key!=keys.end();++key){
if(!key->empty()){
// connect dummy to the signals
this->OnMetadataEvent(key->c_str()).connect( (Query::ListBase*)this,&Query::ListBase::DummySlot);
}
}
}else if(node.Name()=="listtracks"){
this->OnTrackEvent().connect( (Query::ListBase*)this,&Query::ListBase::DummySlotTracks);
}else if(node.Name()=="listtrackinfo"){
this->OnTrackInfoEvent().connect( (Query::ListBase*)this,&Query::ListBase::DummySlotTrackInfo);
}
return true;
}
/// <listeners>genre,artist,album</listeners>
bool Query::ListBase::SendQueryStandardNodes(musik::core::xml::WriterNode &queryNode){
// Then the listeners
xml::WriterNode listenersNode(queryNode,"listeners");
for(MetadataSignals::iterator listener=this->metadataEvent.begin();listener!=this->metadataEvent.end();++listener){
if( listener->second.has_connections() ){
if(!listenersNode.Content().empty()){
listenersNode.Content().append(",");
}
listenersNode.Content().append(listener->first);
}
}
// Then the track listener
if( this->trackEvent.has_connections() ){
xml::WriterNode listTracksNode(queryNode,"listtracks");
listTracksNode.Content().append("true");
}
// Then the track listener
if( this->trackInfoEvent.has_connections() ){
xml::WriterNode listTrackInfoNode(queryNode,"listtrackinfo");
listTrackInfoNode.Content().append("true");
}
return true;
}

View File

@ -49,10 +49,6 @@
//////////////////////////////////////////////////////////////
// Forward declarations
//////////////////////////////////////////////////////////////
/*namespace musik{ namespace core{
class Track;
} }
*/
namespace musik{ namespace core{
@ -78,6 +74,9 @@ namespace musik{ namespace core{
bool ParseTracksSQL(std::string sql,Library::Base *library,db::Connection &db);
bool RecieveQueryStandardNodes(musik::core::xml::ParserNode &node);
bool SendQueryStandardNodes(musik::core::xml::WriterNode &queryNode);
MetadataResults metadataResults;
TrackVector trackResults;

View File

@ -37,6 +37,8 @@
#include "pch.hpp"
#include <core/Query/ListSelection.h>
#include <core/Library/Base.h>
#include <core/xml/ParserNode.h>
#include <core/xml/WriterNode.h>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
@ -459,7 +461,9 @@ bool Query::ListSelection::ParseQuery(Library::Base *library,db::Connection &db)
///A shared_ptr to the Query::Base
//////////////////////////////////////////
Query::Ptr Query::ListSelection::copy() const{
return Query::Ptr(new Query::ListSelection(*this));
Query::Ptr queryCopy(new Query::ListSelection(*this));
queryCopy->PostCopy();
return queryCopy;
}
void Query::ListSelection::SQLPrependWhereOrAnd(std::string &sql){
@ -571,12 +575,10 @@ bool Query::ListSelection::RecieveQuery(musik::core::xml::ParserNode &queryNode)
while( musik::core::xml::ParserNode node = queryNode.ChildNode() ){
if(node.Name()=="selections"){
std::cout << "<selections>";
// Get metakey nodes
// Expected tag is likle this:
// <selection key="genre">2,5,3</selection>
while( musik::core::xml::ParserNode selectionNode = node.ChildNode("selection") ){
std::cout << "<selection key=\"" << selectionNode.Attributes()["key"] << "\">";
// Wait for all content
selectionNode.WaitForContent();
@ -588,34 +590,12 @@ bool Query::ListSelection::RecieveQuery(musik::core::xml::ParserNode &queryNode)
for(StringVector::iterator value=values.begin();value!=values.end();++value){
this->SelectMetadata(selectionNode.Attributes()["key"].c_str(),boost::lexical_cast<DBINT>(*value));
std::cout << "," << *value;
}
std::cout << "</selection>" << std::endl;
}
std::cout << "</selections>" << std::endl;
}else if(node.Name()=="listeners"){
// Wait for all content
node.WaitForContent();
// Secondly, lets look for what to query for
// Split comaseparated list
typedef std::vector<std::string> StringVector;
StringVector keys;
boost::algorithm::split(keys,node.Content(),boost::algorithm::is_any_of(","));
for(StringVector::iterator key=keys.begin();key!=keys.end();++key){
if(!key->empty()){
// connect dummy to the signals
this->OnMetadataEvent(key->c_str()).connect( (Query::ListBase*)this,&Query::ListBase::DummySlot);
}
}
}else if(node.Name()=="listtracks"){
this->OnTrackEvent().connect( (Query::ListBase*)this,&Query::ListBase::DummySlotTracks);
}else if(node.Name()=="listtrackinfo"){
this->OnTrackInfoEvent().connect( (Query::ListBase*)this,&Query::ListBase::DummySlotTrackInfo);
}else{
this->RecieveQueryStandardNodes(node);
}
}
return true;
@ -625,12 +605,11 @@ std::string Query::ListSelection::Name(){
return "ListSelection";
}
bool Query::ListSelection::SendQuery(musik::core::xml::WriterNode &queryNode){
/// <selections>
/// <selection key="genre">1,3,5,7</selection>
/// <selection key="artist">6,7,8</selection>
/// </selections>
/// <listeners>genre,artist,album</listeners>
bool Query::ListSelection::SendQuery(musik::core::xml::WriterNode &queryNode){
xml::WriterNode selectionsNode(queryNode,"selections");
// Start with the selection nodes
@ -651,26 +630,8 @@ bool Query::ListSelection::SendQuery(musik::core::xml::WriterNode &queryNode){
}
// Then the listeners
xml::WriterNode listenersNode(queryNode,"listeners");
for(MetadataSignals::iterator listener=this->metadataEvent.begin();listener!=this->metadataEvent.end();++listener){
if( listener->second.has_connections() ){
if(!listenersNode.Content().empty()){
listenersNode.Content().append(",");
}
listenersNode.Content().append(listener->first);
}
}
// Then the track listener
if( this->trackEvent.has_connections() ){
xml::WriterNode listTracksNode(queryNode,"listtracks");
listTracksNode.Content().append("true");
}
// Then the track listener
if( this->trackInfoEvent.has_connections() ){
xml::WriterNode listTrackInfoNode(queryNode,"listtrackinfo");
listTrackInfoNode.Content().append("true");
}
this->SendQueryStandardNodes(queryNode);
return true;
}

View File

@ -39,11 +39,7 @@
//////////////////////////////////////////////////////////////
// Forward declarations
//////////////////////////////////////////////////////////////
namespace musik{ namespace core{
namespace Library{
class Base;
}
} }
//////////////////////////////////////////////////////////////
#include <boost/shared_ptr.hpp>

View File

@ -38,6 +38,9 @@
#include <core/Query/SortTracks.h>
#include <core/Library/Base.h>
#include <core/config_format.h>
#include <boost/algorithm/string.hpp>
#include <core/xml/ParserNode.h>
#include <core/xml/WriterNode.h>
using namespace musik::core;
@ -177,7 +180,9 @@ bool Query::SortTracks::ParseQuery(Library::Base *library,db::Connection &db){
///A shared_ptr to the Query::Base
//////////////////////////////////////////
Query::Ptr Query::SortTracks::copy() const{
return Query::Ptr(new Query::SortTracks(*this));
Query::Ptr queryCopy(new Query::SortTracks(*this));
queryCopy->PostCopy();
return queryCopy;
}
void Query::SortTracks::AddTrack(int trackId){
@ -207,3 +212,68 @@ void Query::SortTracks::ClearTracks(){
this->tracksToSort.clear();
}
//////////////////////////////////////////
///\brief
///Recieve the query from XML
///
///\param queryNode
///Reference to query XML node
///
///The excpeted input format is like this:
///\code
///<query type="SortTracks">
/// <tracks>1,3,5,7</tracks>
///</query>
///\endcode
///
///\returns
///true when successfully recieved
//////////////////////////////////////////
bool Query::SortTracks::RecieveQuery(musik::core::xml::ParserNode &queryNode){
while( musik::core::xml::ParserNode node = queryNode.ChildNode() ){
if(node.Name()=="tracks"){
node.WaitForContent();
typedef std::vector<std::string> StringVector;
StringVector values;
try{ // lexical_cast can throw
boost::algorithm::split(values,node.Content(),boost::algorithm::is_any_of(","));
for(StringVector::iterator value=values.begin();value!=values.end();++value){
this->tracksToSort.push_back( boost::lexical_cast<DBINT>(*value) );
}
}
catch(...){
return false;
}
}else{
this->RecieveQueryStandardNodes(node);
}
}
return true;
}
std::string Query::SortTracks::Name(){
return "SortTracks";
}
bool Query::SortTracks::SendQuery(musik::core::xml::WriterNode &queryNode){
{
xml::WriterNode tracksNode(queryNode,"tracks");
for(IntVector::iterator trackId=this->tracksToSort.begin();trackId!=this->tracksToSort.end();++trackId){
if(!tracksNode.Content().empty()){
tracksNode.Content().append(",");
}
tracksNode.Content().append(boost::lexical_cast<std::string>(*trackId));
}
}
this->SendQueryStandardNodes(queryNode);
return true;
}

View File

@ -46,14 +46,7 @@
#include <core/Query/ListBase.h>
#include <core/tracklist/IRandomAccess.h>
//////////////////////////////////////////////////////////////
// Forward declarations
//////////////////////////////////////////////////////////////
namespace musik{ namespace core{
namespace Library{
class Base;
}
} }
namespace musik{ namespace core{
@ -74,17 +67,22 @@ namespace musik{ namespace core{
protected:
std::vector<int> tracksToSort;
typedef std::vector<int> IntVector;
IntVector tracksToSort;
std::list<std::string> sortMetaKeys;
friend class Library::Base;
friend class Library::LocalDB;
virtual bool ParseQuery(Library::Base *library,db::Connection &db);
Ptr copy() const;
virtual std::string Name();
virtual bool ParseQuery(Library::Base *library,db::Connection &db);
virtual bool RecieveQuery(musik::core::xml::ParserNode &queryNode);
virtual bool SendQuery(musik::core::xml::WriterNode &queryNode);
private:
};

View File

@ -36,8 +36,10 @@
#include "pch.hpp"
#include <core/Common.h>
#include <core/Query/TrackMetadata.h>
#include <core/Library/Base.h>
#include <boost/algorithm/string.hpp>
using namespace musik::core;
using namespace musik::core::Query;
@ -243,7 +245,7 @@ bool TrackMetadata::RunCallbacks(Library::Base *library){
// First swap the results so that Query can continue to parse
{
boost::mutex::scoped_lock oLock(library->oResultMutex);
boost::mutex::scoped_lock lock(library->oResultMutex);
aResultCopy.swap(this->aResultTracks);
if( (this->status & Status::Ended)!=0){
@ -288,7 +290,9 @@ void TrackMetadata::RequestAllMetakeys(){
}
Query::Ptr TrackMetadata::copy() const{
return Query::Ptr(new Query::TrackMetadata(*this));
Query::Ptr queryCopy(new Query::TrackMetadata(*this));
queryCopy->PostCopy();
return queryCopy;
}
void TrackMetadata::PreAddQuery(Library::Base *library){
@ -297,4 +301,170 @@ void TrackMetadata::PreAddQuery(Library::Base *library){
}
}
std::string TrackMetadata::Name(){
return "TrackMetadata";
}
bool TrackMetadata::RecieveQuery(musik::core::xml::ParserNode &queryNode){
while(musik::core::xml::ParserNode metakeysNode = queryNode.ChildNode()){
if(metakeysNode.Name()=="metakeys"){
if(metakeysNode.Attributes()["all"]=="true"){
this->RequestAllMetakeys();
}else{
metakeysNode.WaitForContent();
StringSet values;
try{ // lexical_cast can throw
boost::algorithm::split(values,metakeysNode.Content(),boost::algorithm::is_any_of(","));
this->RequestMetakeys(values);
}
catch(...){
return false;
}
}
}else if(metakeysNode.Name()=="tracks"){
metakeysNode.WaitForContent();
typedef std::vector<std::string> StringVector;
StringVector values;
try{ // lexical_cast can throw
boost::algorithm::split(values,metakeysNode.Content(),boost::algorithm::is_any_of(","));
for(StringVector::iterator value=values.begin();value!=values.end();++value){
this->RequestTrack(TrackPtr(new Track( boost::lexical_cast<DBINT>(*value) )));
}
}
catch(...){
return false;
}
}
}
return true;
}
bool TrackMetadata::SendQuery(musik::core::xml::WriterNode &queryNode){
{
musik::core::xml::WriterNode metakeysNode(queryNode,"metakeys");
if(this->requestAllFields){
metakeysNode.Attributes()["all"] = "true";
}else{
for(StringSet::iterator metakey=this->requestedFields.begin();metakey!=this->requestedFields.end();++metakey){
if(!metakeysNode.Content().empty()){
metakeysNode.Content().append(",");
}
metakeysNode.Content().append(*metakey);
}
}
}
{
musik::core::xml::WriterNode tracksNode(queryNode,"tracks");
for(TrackVector::iterator track=this->aRequestTracks.begin();track!=this->aRequestTracks.end();++track){
if(!tracksNode.Content().empty()){
tracksNode.Content().append(",");
}
tracksNode.Content().append( boost::lexical_cast<std::string>( (*track)->id ) );
}
}
return true;
}
bool TrackMetadata::SendResults(musik::core::xml::WriterNode &queryNode,Library::Base *library){
bool continueSending(true);
while(continueSending){
TrackVector resultCopy;
{
boost::mutex::scoped_lock lock(library->oResultMutex);
resultCopy.swap(this->aResultTracks);
if( (this->status & Status::Ended)!=0){
continueSending = false;
}
}
// Send the results
if( !resultCopy.empty() ){
try{
for(TrackVector::iterator track=resultCopy.begin();track!=resultCopy.end();++track){
musik::core::xml::WriterNode trackNode(queryNode,"t");
trackNode.Attributes()["id"] = boost::lexical_cast<std::string>( (*track)->id );
TrackMeta::TagMapIteratorPair metaDatas( (*track)->GetAllValues() );
for(TrackMeta::TagMapConstIterator metaData=metaDatas.first;metaData!=metaDatas.second;++metaData){
musik::core::xml::WriterNode metaDataNode(trackNode,"md");
metaDataNode.Attributes()["k"] = metaData->first;
metaDataNode.Content().append( ConvertUTF8(metaData->second) );
}
}
}
catch(...){
return false;
}
}
// Wait for more results
if( continueSending && resultCopy.empty()){
boost::thread::yield();
}
}
return true;
}
bool TrackMetadata::RecieveResults(musik::core::xml::ParserNode &queryNode,Library::Base *library){
while(musik::core::xml::ParserNode trackNode=queryNode.ChildNode("t") ){
try{
DBINT trackId( boost::lexical_cast<DBINT>(trackNode.Attributes()["id"]) );
// Find the track in the aRequestTracks
TrackVector::iterator track=this->aRequestTracks.begin();
bool trackFound(false);
while(track!=this->aRequestTracks.end() && !trackFound){
if( (*track)->id==trackId ){
// TrackPtr found
trackFound = true;
}else{
++track;
}
}
if(track!=this->aRequestTracks.end() && trackFound){
TrackPtr currentTrack(*track);
// Remove the track from the aRequestTracks
this->aRequestTracks.erase(track);
// Get the metadata
while(musik::core::xml::ParserNode metadataNode=trackNode.ChildNode("md") ){
metadataNode.WaitForContent();
currentTrack->SetValue( metadataNode.Attributes()["k"].c_str(),ConvertUTF16(metadataNode.Content()).c_str());
}
{
boost::mutex::scoped_lock oLock(library->oResultMutex);
this->aResultTracks.push_back(currentTrack);
}
}
}
catch(...){
return false;
}
}
return true;
}

View File

@ -72,10 +72,11 @@ class TrackMetadata : public Query::Base {
TrackMetadataEvent OnTracksEvent;
private:
std::set<std::string> requestedFields;
typedef std::set<std::string> StringSet;
StringSet requestedFields;
std::vector<std::string> fieldOrder;
std::set<std::string> metaFields;
std::set<std::string> categoryFields;
StringSet metaFields;
StringSet categoryFields;
std::string sSQL;
std::string sSQLTables;
std::string sSQLWhere;
@ -89,9 +90,17 @@ class TrackMetadata : public Query::Base {
protected:
friend class Library::Base;
friend class Library::LocalDB;
bool ParseQuery(Library::Base *library,db::Connection &db);
Ptr copy() const;
void PreAddQuery(Library::Base *library);
virtual bool ParseQuery(Library::Base *library,db::Connection &db);
virtual std::string Name();
virtual bool RecieveQuery(musik::core::xml::ParserNode &queryNode);
virtual bool SendQuery(musik::core::xml::WriterNode &queryNode);
virtual bool SendResults(musik::core::xml::WriterNode &queryNode,Library::Base *library);
virtual bool RecieveResults(musik::core::xml::ParserNode &queryNode,Library::Base *library);
};
//////////////////////////////////////////////////////////////////////////////

View File

@ -154,8 +154,8 @@ bool Track::CompareDBAndFileInfo(const boost::filesystem::utfpath &file,db::Conn
this->SetValue("extension",file.leaf().substr(lastDot+1).c_str());
}
DBINT fileSize = boost::filesystem::file_size(file);
DBTIME fileTime = boost::filesystem::last_write_time(file);
DBINT fileSize = (DBINT)boost::filesystem::file_size(file);
DBTIME fileTime = (DBTIME)boost::filesystem::last_write_time(file);
this->SetValue("filesize",boost::lexical_cast<utfstring>(fileSize).c_str());
this->SetValue("filetime",boost::lexical_cast<utfstring>(fileTime).c_str());

View File

@ -105,12 +105,20 @@ void Connection::ReadThread(){
if(queryIt!=queryMap.end()){
// Query type exists, lets create a copy
musik::core::Query::Ptr query( queryIt->second->copy() );
query->queryId = boost::lexical_cast<unsigned int>(queryNode.Attributes()["id"]);
try{
query->queryId = boost::lexical_cast<unsigned int>(queryNode.Attributes()["id"]);
query->uniqueId = boost::lexical_cast<unsigned int>(queryNode.Attributes()["uid"]);
}catch(...){}
if(query->RecieveQuery(queryNode)){
unsigned int options(0);
try{
options = boost::lexical_cast<unsigned int>(queryNode.Attributes()["options"]);
}catch(...){}
// TODO: check for AddQuery options in tag
this->AddQuery( *query,boost::lexical_cast<unsigned int>(queryNode.Attributes()["options"]) );
this->AddQuery( *query,options|musik::core::Query::CopyUniqueId );
}
@ -213,6 +221,7 @@ void Connection::WriteThread(){
musik::core::xml::WriterNode queryNode(musikNode,"queryresults");
queryNode.Attributes()["type"] = sendQuery->Name();
queryNode.Attributes()["id"] = boost::lexical_cast<std::string>(sendQuery->queryId);
queryNode.Attributes()["uid"] = boost::lexical_cast<std::string>(sendQuery->uniqueId);
sendQuery->SendResults(queryNode,this);
}

View File

@ -148,20 +148,22 @@ void Standard::OnTracksFromQuery(musik::core::TrackVector *newTracks,bool clear)
}
void Standard::LoadTrack(int position){
int trackCount(0);
for(int i(position);i<position+this->hintedRows;++i){
if(this->QueryForTrack(i)){
++trackCount;
if(this->QueryForTrack(position)){
int trackCount(1);
for(int i(position+1);i<position+this->hintedRows;++i){
if(this->QueryForTrack(i)){
++trackCount;
}
}
if(trackCount && this->library){
this->library->AddQuery(this->trackQuery,musik::core::Query::Prioritize);
this->trackQuery.Clear();
}
}
if(trackCount && this->library){
this->library->AddQuery(this->trackQuery,musik::core::Query::Prioritize);
this->trackQuery.Clear();
}
}
bool Standard::QueryForTrack(int position){

View File

@ -38,6 +38,8 @@
#include <core/xml/ParserNode.h>
#include <expat/expat.h>
#include <fstream>
using namespace musik::core::xml;
//////////////////////////////////////////////////////////////////////////////
@ -157,6 +159,11 @@ void Parser::ReadFromSocket(){
this->Exit();
}
// Log
// std::ofstream logFile("mc2_Parser.log",std::ios::app);
// logFile.write(this->readBuffer.c_array(),this->readBufferLength);
// logFile << std::endl;
}
//////////////////////////////////////////////////////////////////////////////

View File

@ -37,6 +37,7 @@
#include <core/xml/Writer.h>
#include <core/xml/WriterNode.h>
#include <boost/algorithm/string/replace.hpp>
#include <fstream>
using namespace musik::core::xml;
@ -175,9 +176,16 @@ void Writer::Send(){
// Time to send the buffer
if(!sendBuffer.empty()){
boost::asio::write(*(this->socket),boost::asio::buffer(sendBuffer));
// Log
//std::ofstream logFile("mc2_Writer.log",std::ios::app);
//logFile << sendBuffer << std::endl;
sendBuffer.clear();
}
}
catch(boost::system::error_code &error){
this->Exit();
}
catch(...){
this->Exit();
}