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.36 2000/01/19 22:20:29 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 <sys/stat.h>
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#include "win32impl.h"
#endif
#include <string>
#include <algorithm>
#if !defined(WIN32)
#include <strstream>
typedef ostrstream ostringstream;
#else
#include <sstream>
#endif
using namespace std;
#include "config.h"
#include "musiccatalog.h"
#include "player.h"
#include "utility.h"
#include "debug.h"
#define METADATABASE_VERSION 1
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_inUpdateSong = false;
m_acceptItemChanged = false;
m_artistList = new vector<ArtistList *>;
m_unsorted = new vector<PlaylistItem *>;
m_playlists = new vector<string>;
m_streams = new vector<PlaylistItem *>;
if (databasepath)
SetDatabase(databasepath);
}
MusicCatalog::~MusicCatalog()
{
vector<ArtistList *>::iterator a;
vector<PlaylistItem *>::iterator p;
if (m_database)
delete m_database;
for(a = m_artistList->begin(); a != m_artistList->end(); a++)
delete (*a);
delete m_artistList;
for(p = m_unsorted->begin(); p != m_unsorted->end(); p++)
delete (*p);
delete m_unsorted;
for(p = m_streams->begin(); p != m_streams->end(); p++)
delete (*p);
delete m_streams;
delete m_playlists;
delete m_mutex;
delete m_catMutex;
}
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;
m_database->Remove(url);
m_catMutex->Acquire();
vector<PlaylistItem *>::iterator i = m_streams->begin();
for (; i != m_streams->end(); i++)
if ((*i)->URL() == url) {
AcceptEvent(new MusicCatalogStreamRemovedEvent(*i));
m_streams->erase(i);
break;
}
m_catMutex->Release();
delete meta;
return kError_NoErr;
}
Error MusicCatalog::RemoveSong(const char *url)
{
assert(url);
if (!m_database->Working())
return kError_DatabaseNotWorking;
MetaData *meta = ReadMetaDataFromDatabase(url);
if (!meta)
return kError_ItemNotFound;
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);
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 (meta->Artist() == (*i)->name)
{
alList = (*i)->m_albumList;
j = alList->begin();
for (; j != alList->end() && !found; j++)
{
if (meta->Album() == (*j)->name)
{
trList = (*j)->m_trackList;
k = trList->begin();
for (; k != trList->end() && !found; k++)
if (url == (*k)->URL())
{
AcceptEvent(new MusicCatalogTrackRemovedEvent(*k, *i, *j));
trList->erase(k);
found = true;
break;
}
if (trList->size() == 0)
alList->erase(j);
}
}
if (alList->size() == 0)
m_artistList->erase(i);
}
}
}
delete meta;
m_catMutex->Release();
return kError_NoErr;
}
Error MusicCatalog::AddStream(const char *url)
{
assert(url);
if (!m_database->Working())
return kError_DatabaseNotWorking;
PlaylistItem *newstream;
MetaData *meta = ReadMetaDataFromDatabase(url);
if (!meta)
return kError_DatabaseNotWorking;
newstream = new PlaylistItem(url, meta);
m_catMutex->Acquire();
vector<PlaylistItem *>::iterator i = m_streams->begin();
for (; i != m_streams->end(); i++)
if ((*i)->URL() == url)
return kError_DuplicateItem;
m_streams->push_back(newstream);
AcceptEvent(new MusicCatalogStreamAddedEvent(newstream));
m_catMutex->Release();
return kError_NoErr;
}
Error MusicCatalog::AddSong(const char *url)
{
assert(url);
if (!m_database->Working())
return kError_DatabaseNotWorking;
PlaylistItem *newtrack;
MetaData *meta = ReadMetaDataFromDatabase(url);
if (!meta) {
newtrack = new PlaylistItem(url);
m_context->plm->RetrieveMetaData(newtrack);
while (newtrack->GetState() != kPlaylistItemState_Normal)
usleep(5);
MetaData tempdata = (MetaData)(newtrack->GetMetaData());
WriteMetaDataToDatabase(url, tempdata);
delete newtrack;
meta = ReadMetaDataFromDatabase(url);
}
newtrack = new PlaylistItem(url, meta);
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)
return kError_DuplicateItem;
m_unsorted->push_back(newtrack);
AcceptEvent(new MusicCatalogTrackAddedEvent(newtrack, NULL, NULL));
}
else {
bool changed = false;
if (meta->Album() == " " || meta->Album().size() == 0) {
string unknownstr = string("Unknown");
meta->SetAlbum(unknownstr.c_str());
changed = true;
}
if (meta->Title() == " " || meta->Title().size() == 0) {
string unknownstr = string("Unknown");
meta->SetTitle(unknownstr.c_str());
changed = true;
}
if (changed)
WriteMetaDataToDatabase(url, *meta);
bool found_artist = false;
vector<ArtistList *>::iterator i = m_artistList->begin();
for (; i != m_artistList->end(); i++) {
if (meta->Artist() == (*i)->name) {
bool found_album = false;
found_artist = true;
vector<AlbumList *> *alList = (*i)->m_albumList;
vector<AlbumList *>::iterator j = alList->begin();
for (; j != alList->end(); j++) {
if (meta->Album() == (*j)->name) {
found_album = true;
vector<PlaylistItem *> *trList = (*j)->m_trackList;
vector<PlaylistItem *>::iterator k = trList->begin();
for (; k != trList->end(); k++) {
if ((*k)->URL() == url) {
delete newtrack;
m_catMutex->Release();
return kError_DuplicateItem;
}
}
(*j)->m_trackList->push_back(newtrack);
AcceptEvent(new MusicCatalogTrackAddedEvent(newtrack, *i, *j));
break;
}
}
if (!found_album) {
AlbumList *newalbum = new AlbumList;
newalbum->name = meta->Album();
newalbum->m_trackList->push_back(newtrack);
alList->push_back(newalbum);
AcceptEvent(new MusicCatalogTrackAddedEvent(newtrack, (*i), newalbum));
break;
}
}
}
if (!found_artist) {
ArtistList *newartist = new ArtistList;
newartist->name = meta->Artist();
AlbumList *newalbum = new AlbumList;
newalbum->name = meta->Album();
newalbum->m_trackList->push_back(newtrack);
newartist->m_albumList->push_back(newalbum);
m_artistList->push_back(newartist);
AcceptEvent(new MusicCatalogTrackAddedEvent(newtrack, newartist, newalbum));
}
}
delete meta;
m_catMutex->Release();
return kError_NoErr;
}
Error MusicCatalog::UpdateSong(PlaylistItem *item)
{
assert(item);
if (!m_database->Working())
return kError_DatabaseNotWorking;
m_inUpdateSong = true;
Error err = RemoveSong(item->URL().c_str());
if (IsError(err))
return err;
WriteMetaDataToDatabase(item->URL().c_str(), item->GetMetaData());
m_database->Sync();
err = AddSong(item->URL().c_str());
if (IsError(err))
return err;
m_inUpdateSong = false;
m_context->target->AcceptEvent(new MusicCatalogTrackChangedEvent(m_oldItem, m_newItem, m_oldArtist, m_newArtist, m_oldAlbum, m_newAlbum));
return kError_NoErr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -