📄 musiccatalog.cpp
字号:
/*____________________________________________________________________________
FreeAmp - The Free MP3 Player
Portions Copyright (C) 1999 EMusic.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: musiccatalog.cpp,v 1.103 2001/03/05 21:54:47 ijr Exp $
____________________________________________________________________________*/
// The debugger can't handle symbols more than 255 characters long.
// STL often creates symbols longer than that.
// When symbols are longer than 255 characters, the warning is disabled.
#ifdef WIN32
#pragma warning(disable:4786)
#endif
#include "config.h"
#include <sys/stat.h>
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#include "win32impl.h"
#endif
#include <string>
#include <algorithm>
using namespace std;
#include "musiccatalog.h"
#include "player.h"
#include "utility.h"
#include "pmo.h"
#include "debug.h"
#define METADATABASE_VERSION 1
#define DATABASE_SUB_VERSION 3
MusicCatalog::MusicCatalog(FAContext *context, char *databasepath)
{
m_database = NULL;
m_context = context;
m_plm = context->plm;
m_mutex = new Mutex();
m_catMutex = new Mutex();
m_timerMutex = new Mutex();
m_MBLookupLock = new Mutex();
m_inUpdateSong = false;
m_addImmediately = false;
m_bSurpressAddMessages = false;
m_trackCount = 0;
m_artistList = new vector<ArtistList *>;
m_unsorted = new vector<PlaylistItem *>;
m_playlists = new vector<string>;
m_streams = new vector<PlaylistItem *>;
m_sigs = new set<string>;
m_guidTable = new multimap<string, string, less<string> >;
m_MBRequests = new vector<pair<string, string> >;
m_watchTimer = NULL;
m_killGUIDs = false;
m_killMBThread = false;
m_MBLookupThreadActive = false;
m_pendingMBLookups = 0;
m_timeout = 0;
context->prefs->GetPrefInt32(kWatchThisDirTimeoutPref, &m_timeout);
if (databasepath)
SetDatabase(databasepath);
}
void MusicCatalog::StartTimer(void)
{
if (m_timeout > 0) {
WatchTimer();
m_context->timerManager->StartTimer(&m_watchTimer, watch_timer,
m_timeout, this);
}
}
MusicCatalog::~MusicCatalog()
{
m_killMBThread = true;
while (m_MBLookupThreadActive)
usleep(50);
ClearCatalog();
StopSearchMusic();
m_mutex->Acquire();
m_catMutex->Acquire();
m_timerMutex->Acquire();
if(m_watchTimer)
m_context->timerManager->StopTimer(m_watchTimer);
delete m_artistList;
delete m_unsorted;
delete m_streams;
delete m_sigs;
if (m_database)
delete m_database;
delete m_playlists;
delete m_mutex;
delete m_catMutex;
delete m_timerMutex;
delete m_guidTable;
}
string MusicCatalog::GetFilename(const string &strGUID)
{
if ((!m_guidTable) || (m_guidTable->size() == 0))
return "";
multimap<string, string, less<string> >::iterator i;
i = m_guidTable->find(strGUID);
if (i != m_guidTable->end())
return (*i).second;
return "";
}
class comp_catalog {
public:
bool operator()(PlaylistItem *a, PlaylistItem *b)
{
if (a->GetMetaData().Track() == b->GetMetaData().Track())
// sort alphabetically...
return (a->GetMetaData().Title() < b->GetMetaData().Title());
return (a->GetMetaData().Track() < b->GetMetaData().Track());
}
bool operator()(AlbumList *a, AlbumList *b)
{
return (a->name < b->name);
}
bool operator()(ArtistList *a, ArtistList *b)
{
return (a->name < b->name);
}
};
void MusicCatalog::Sort(void)
{
m_catMutex->Acquire();
// Sort the playlists...
sort(m_playlists->begin(), m_playlists->end());
// Sort the uncategorized tracks
sort(m_unsorted->begin(), m_unsorted->end(), comp_catalog());
// Sort the rest o the junk
vector<ArtistList *>::iterator i = m_artistList->begin();
for (; i != m_artistList->end(); i++) {
vector<AlbumList *>::iterator j = (*i)->m_albumList->begin();
for (; j != (*i)->m_albumList->end(); j++) {
sort((*j)->m_trackList->begin(), (*j)->m_trackList->end(),
comp_catalog());
}
sort((*i)->m_albumList->begin(), (*i)->m_albumList->end(),
comp_catalog());
}
sort(m_artistList->begin(), m_artistList->end(), comp_catalog());
// Sort the streams
sort(m_streams->begin(), m_streams->end(), comp_catalog());
m_catMutex->Release();
}
Error MusicCatalog::RemovePlaylist(const char *url)
{
assert(url);
if (!m_database->Working())
return kError_DatabaseNotWorking;
char *data = m_database->Value(url);
if (!data)
return kError_ItemNotFound;
delete [] data;
m_database->Remove(url);
m_catMutex->Acquire();
vector<string>::iterator i = m_playlists->begin();
for (; i != m_playlists->end(); i++)
if ((*i) == url) {
string tempstr = url;
if (tempstr.find("currentlist.m3u") >= tempstr.length()) {
string sUrl = url;
m_context->target->AcceptEvent(new MusicCatalogPlaylistRemovedEvent(sUrl));
m_playlists->erase(i);
}
m_catMutex->Release();
return kError_NoErr;
}
m_catMutex->Release();
return kError_ItemNotFound;
}
Error MusicCatalog::AddPlaylist(const char *url)
{
assert(url);
if (!m_database->Working())
return kError_DatabaseNotWorking;
char *data = m_database->Value(url);
if (!data)
m_database->Insert(url, "P");
else
delete [] data;
bool found = false;
m_catMutex->Acquire();
vector<string>::iterator i = m_playlists->begin();
for (; i != m_playlists->end(); i++)
if ((*i) == url)
found = true;
if (!found) {
string tempstr = url;
if (tempstr.find("currentlist.m3u") < tempstr.length())
m_playlists->insert(m_playlists->begin(), url);
else
m_playlists->push_back(url);
string sUrl = url;
m_context->target->AcceptEvent(new MusicCatalogPlaylistAddedEvent(sUrl));
m_catMutex->Release();
return kError_NoErr;
}
m_catMutex->Release();
return kError_DuplicateItem;
}
Error MusicCatalog::RemoveStream(const char *url)
{
assert(url);
if (!m_database->Working())
return kError_DatabaseNotWorking;
MetaData *meta = ReadMetaDataFromDatabase(url);
if (!meta)
return kError_ItemNotFound;
string strGUID = meta->GUID();
m_database->Remove(url);
m_catMutex->Acquire();
vector<PlaylistItem *>::iterator i = m_streams->begin();
for (; i != m_streams->end(); i++)
if ((*i)->URL() == url) {
m_context->target->AcceptEvent(new MusicCatalogStreamRemovedEvent(*i));
delete (*i);
m_streams->erase(i);
break;
}
if ((strGUID.size() != 0) && (m_guidTable->size() != 0)) {
multimap<string, string, less<string> >::iterator i;
i = m_guidTable->find(strGUID);
while ((i != m_guidTable->end()) && ((*i).first == strGUID)) {
if ((*i).second == url) {
m_guidTable->erase(i);
break;
}
i++;
}
}
m_catMutex->Release();
delete meta;
return kError_NoErr;
}
PlaylistItem *MusicCatalog::GetPlaylistItemFromURL(const char *url)
{
assert(url);
PlaylistItem *retitem = NULL;
if (!m_database->Working())
return retitem;
MetaData *meta = ReadMetaDataFromDatabase(url);
if (!meta)
return retitem;
m_catMutex->Acquire();
if ((meta->Artist().size() == 0) || (meta->Artist() == " ")) {
vector<PlaylistItem *>::iterator i = m_unsorted->begin();
for (; i != m_unsorted->end(); i++)
if ((*i)->URL() == url)
{
retitem = *i;
break;
}
}
else
{
vector<ArtistList *>::iterator i;
vector<AlbumList *> *alList;
vector<AlbumList *>::iterator j;
vector<PlaylistItem *> *trList;
vector<PlaylistItem *>::iterator k;
bool found = false;
i = m_artistList->begin();
for (; i != m_artistList->end() && !found; i++)
{
if (CaseCompare(meta->Artist(),(*i)->name))
{
alList = (*i)->m_albumList;
j = alList->begin();
for (; j != alList->end() && !found; j++)
{
if (CaseCompare(meta->Album(),(*j)->name))
{
trList = (*j)->m_trackList;
k = trList->begin();
for (; k != trList->end() && !found; k++)
if (url == (*k)->URL())
{
retitem = *k;
found = true;
break;
}
}
}
}
}
}
delete meta;
m_catMutex->Release();
return retitem;
}
Error MusicCatalog::RemoveSong(const char *url)
{
assert(url);
if (!m_database->Working())
return kError_DatabaseNotWorking;
MetaData *meta = ReadMetaDataFromDatabase(url);
if (!meta)
return kError_ItemNotFound;
string strGUID = meta->GUID();
m_database->Remove(url);
m_catMutex->Acquire();
if ((meta->Artist().size() == 0) || (meta->Artist() == " ")) {
vector<PlaylistItem *>::iterator i = m_unsorted->begin();
for (; i != m_unsorted->end(); i++)
if ((*i)->URL() == url)
{
AcceptEvent(new MusicCatalogTrackRemovedEvent(*i, NULL, NULL));
m_unsorted->erase(i);
m_trackCount--;
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -