欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

musiccatalog.cpp

这是一个mp3的源代码
CPP
第 1 页 / 共 2 页
字号:
/*____________________________________________________________________________

        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 + -