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

musiccatalog.cpp

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

Error MusicCatalog::Remove(const char *url)
{
    assert(url);

    if (!m_database->Working())
        return kError_DatabaseNotWorking;

    char *data = m_database->Value(url);
    if (!data)
        return kError_ItemNotFound;

    Error retvalue = kError_YouScrewedUp;

    if (!strncmp("P", data, 1))
        retvalue = RemovePlaylist(url);
    else if (!strncmp("M", data, 1))
        retvalue = RemoveSong(url);
    else if (!strncmp("S", data, 1))
        retvalue = RemoveStream(url);

    delete [] data;

    return retvalue;
}

Error MusicCatalog::Add(const char *url)
{
    assert(url);

    if (!m_database->Working())
        return kError_DatabaseNotWorking;

    char *data = m_database->Value(url);
    if (!data)
        return kError_ItemNotFound;

    Error retvalue = kError_YouScrewedUp;

    if (!strncmp("P", data, 1))
        retvalue = AddPlaylist(url);
    else if (!strncmp("M", data, 1)) 
        retvalue = AddSong(url);
    else if (!strncmp("S", data, 1))
        retvalue = AddStream(url);

    delete [] data;

    return retvalue;
}

void MusicCatalog::ClearCatalog()
{
    m_catMutex->Acquire();
    delete m_artistList;
    delete m_unsorted;
    delete m_playlists;
    delete m_streams;
    m_artistList = new vector<ArtistList *>;
    m_unsorted = new vector<PlaylistItem *>;
    m_playlists = new vector<string>;
    m_streams = new vector<PlaylistItem *>;
    m_catMutex->Release();
    m_context->target->AcceptEvent(new Event(INFO_MusicCatalogCleared));
}

Error MusicCatalog::RePopulateFromDatabase()
{
    if (!m_database->Working())
        return kError_DatabaseNotWorking;

    ClearCatalog();
 
    char *key = m_database->NextKey(NULL);
    Error err = kError_NoErr;

    while (key) {
        err = Add(key);

        if (IsError(err)) {
             m_context->target->AcceptEvent(new ErrorMessageEvent("There was an internal error during generation of the Music Catalog"));
             return kError_YouScrewedUp;
        }
            
        key = m_database->NextKey(key);
    }
    return kError_NoErr;
}

void MusicCatalog::SetDatabase(const char *path)
{
    if (m_database)
        delete m_database;

    m_database = new Database(path, METADATABASE_VERSION);

    if (!m_database->Working()) {
        delete m_database;
        m_database = NULL;
    }

    PruneDatabase();

    if (m_database) {
        RePopulateFromDatabase();
        Sort();
    }
}

void MusicCatalog::PruneDatabase(void)
{
    char *key = m_database->NextKey(NULL);
    struct stat st;

    while (key) {
        if (!strncmp("file://", key, 7)) {
            uint32 length = strlen(key) + 1;
            char *filename = new char[length];

            if (IsntError(URLToFilePath(key, filename, &length)))
                if (-1 == stat(filename, &st)) {
                    m_database->Remove(key);
                    key = NULL;
                }

            delete [] filename;
        }
        key = m_database->NextKey(key);
    }
}

typedef struct MusicSearchThreadStruct {
    MusicCatalog *mc;
    vector<string> pathList;
    Thread *thread;
} MusicSearchThreadStruct;

void MusicCatalog::SearchMusic(vector<string> &pathList)
{
    if (!m_database->Working())
        return;

    Thread *thread = Thread::CreateThread();

    if (thread) {
        MusicSearchThreadStruct *mst = new MusicSearchThreadStruct;

        mst->mc = this;
        mst->pathList = pathList;
        mst->thread = thread;

        thread->Create(musicsearch_thread_function, mst);
    }
}

void MusicCatalog::StopSearchMusic(void)
{
    m_exit = true;
}

void MusicCatalog::musicsearch_thread_function(void *arg)
{
    MusicSearchThreadStruct *mst = (MusicSearchThreadStruct *)arg;

    mst->mc->m_mutex->Acquire();

    mst->mc->m_exit = false;
    mst->mc->DoSearchPaths(mst->pathList);

    mst->mc->AcceptEvent(new Event(INFO_SearchMusicDone));

    mst->mc->m_mutex->Release();

    delete mst->thread;
    delete mst;
}

void MusicCatalog::DoSearchPaths(vector<string> &pathList)
{
    vector<string>::iterator i;
    
    m_acceptItemChanged = true;
    m_itemWaitCount = 0;

    for(i = pathList.begin(); i != pathList.end(); i++)
        DoSearchMusic((char *)(*i).c_str());

    while (m_itemWaitCount > 0)
        usleep(5);
    m_acceptItemChanged = false;
}

void MusicCatalog::DoSearchMusic(char *path)
{
    vector<PlaylistItem *> *metalist = new vector<PlaylistItem *>;

    WIN32_FIND_DATA find;
    HANDLE handle;
    string search = path;

#ifndef WIN32
    if (!strcmp(path, "/dev") || !strcmp(path, "/proc"))
        return;
#endif
 
    string *info = new string("Searching: ");
    (*info) += path;
    m_context->player->AcceptEvent(new BrowserMessageEvent(info->c_str()));
    delete info;
   
    if (search[search.size() - 1] != DIR_MARKER)
       search.append(DIR_MARKER_STR);

    search.append("*");
#ifdef WIN32
    search.append(".*");
#endif

    handle = FindFirstFile((char *)search.c_str(), &find);

    if (handle != INVALID_HANDLE_VALUE)
    {
        do
        {
            char *fileExt;
#ifndef WIN32
            if (find.dwFileAttributes == FILE_ATTRIBUTE_SYMLINK)
                continue;
#endif
            if (find.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
            {
                if (!(!strcmp("." , find.cFileName) || !strcmp("..", find.cFileName)))
                {
                    string newDir = path; 
                    if (path[strlen(path) - 1] != DIR_MARKER)
                        newDir.append(DIR_MARKER_STR);
                    newDir.append(find.cFileName);

                    DoSearchMusic((char *)newDir.c_str());
                }
            }
            else if ((fileExt = m_context->player->GetExtension(find.cFileName)))
            {
                if (m_plm->IsSupportedPlaylistFormat(fileExt) && 
                    strcmp("currentlist.m3u", find.cFileName))
                {
                    string file = path;
                    file.append(DIR_MARKER_STR);
                    file.append(find.cFileName);

                    uint32 urlLength = strlen(file.c_str()) + 10;
                    char *url = new char[urlLength];

                    if (IsntError(FilePathToURL(file.c_str(), url, &urlLength)))
                        m_database->Insert(url, "P");

                    delete [] url;
                }
                else if (m_context->player->IsSupportedExtension(fileExt))
                {
                    string file = path;
                    file.append(DIR_MARKER_STR);
                    file.append(find.cFileName);

                    char *tempurl = new char[file.length() + 10];
                    uint32 length = file.length() + 10;

                    if (IsError(FilePathToURL(file.c_str(), tempurl, &length)))
                    {
                        continue;
                    }
                       
                    PlaylistItem *plist = new PlaylistItem(tempurl);
                    metalist->push_back(plist);
                    m_itemWaitCount++;

                    delete [] tempurl;
                }
                delete fileExt;
            }
        }
        while (FindNextFile(handle, &find) && !m_exit);
        FindClose(handle);

        if (metalist->size() > 0)
            m_plm->RetrieveMetaData(metalist);
        else 
            delete metalist;
    }
}

void MusicCatalog::WriteMetaDataToDatabase(const char *url, 
                                           const MetaData metadata,
                                           MetadataStorageType type)
{
    if (!m_database->Working())
        return;

    ostringstream ost;
    char num[256];
    const char *kDatabaseDelimiter = " ";

    if (type == kTypeStream)
        ost << "S" << kDatabaseDelimiter;
    else
        ost << "M" << kDatabaseDelimiter;

    ost << 9 << kDatabaseDelimiter;

    ost << metadata.Artist().size() << kDatabaseDelimiter;
    ost << metadata.Album().size() << kDatabaseDelimiter;
    ost << metadata.Title().size() << kDatabaseDelimiter;
    ost << metadata.Comment().size() << kDatabaseDelimiter;
    ost << metadata.Genre().size() << kDatabaseDelimiter;

    sprintf(num, "%ld", (long int)metadata.Year());
    ost << strlen(num) << kDatabaseDelimiter;
    sprintf(num, "%ld", (long int)metadata.Track());
    ost << strlen(num) << kDatabaseDelimiter;
    sprintf(num, "%ld", (long int)metadata.Time());
    ost << strlen(num) << kDatabaseDelimiter;
    sprintf(num, "%ld", (long int)metadata.Size());
    ost << strlen(num) << kDatabaseDelimiter;

    ost << metadata.Artist();
    ost << metadata.Album();
    ost << metadata.Title();
    ost << metadata.Comment();
    ost << metadata.Genre();
    ost << metadata.Year();
    ost << metadata.Track();
    ost << metadata.Time();
    ost << metadata.Size();
    ost << '\0';

#ifdef WIN32
    m_database->Insert(url, (char *)ost.str().c_str());
#else
    m_database->Insert(url, (char *)ost.str());
#endif
}

MetaData *MusicCatalog::ReadMetaDataFromDatabase(const char *url)
{
    if (!m_database->Working())
        return NULL;

    char *dbasedata = m_database->Value(url);

    if (!dbasedata)
        return NULL;

    MetaData *metadata = new MetaData();
    char *value = dbasedata + 2;

    uint32 numFields = 0;
    int offset = 0;

    sscanf(value, "%lu%n", (long unsigned int *)&numFields, &offset);
    uint32* fieldLength =  new uint32[numFields];

    for(uint32 i = 0; i < numFields; i++)
    {
        int temp;

        sscanf(value + offset, " %lu %n", (long unsigned int *)&fieldLength[i],
	                                  &temp);

        if (i == numFields - 1) {
            char intholder[10];
            sprintf(intholder, "%lu", (long unsigned int)fieldLength[i]);
            offset += strlen(intholder) + 1;
        }
        else
            offset += temp;
    }

    string data = value;
    data.erase(0, offset);

    uint32 count = 0;

    for(uint32 j = 0; j < numFields; j++)
    {
        if (fieldLength[j] == 0) 
            continue;

        switch(j)
        {
            case 0:
                metadata->SetArtist(data.substr(count, fieldLength[j]).c_str());
                break;
            case 1:
                metadata->SetAlbum(data.substr(count, fieldLength[j]).c_str());
                break;
            case 2:
                metadata->SetTitle(data.substr(count, fieldLength[j]).c_str());
                break;
            case 3:
                metadata->SetComment(data.substr(count, fieldLength[j]).c_str());
                break;
            case 4:
                metadata->SetGenre(data.substr(count, fieldLength[j]).c_str());
                break;
            case 5:
                metadata->SetYear(atoi(data.substr(count, fieldLength[j]).c_str()));
                break;
            case 6:
                metadata->SetTrack(atoi(data.substr(count, fieldLength[j]).c_str()));
                break;
            case 7:
                metadata->SetTime(atoi(data.substr(count, fieldLength[j]).c_str()));
                break;
            case 8:
                metadata->SetSize(atoi(data.substr(count, fieldLength[j]).c_str()));
                break;
            default:
                break;

        }

        count += fieldLength[j];
    }

    delete [] fieldLength;

    delete [] dbasedata;

    return metadata;
}

int32 MusicCatalog::AcceptEvent(Event *e)
{
    switch (e->Type()) {
        case INFO_MusicCatalogTrackRemoved: {
            if (m_inUpdateSong) {
                MusicCatalogTrackRemovedEvent *mctr = 
                                             (MusicCatalogTrackRemovedEvent *)e;
                m_oldItem = (PlaylistItem *)mctr->Item();
                m_oldArtist = (ArtistList *)mctr->Artist();
                m_oldAlbum = (AlbumList *)mctr->Album();
     
                delete e;
            }
            else 
                m_context->target->AcceptEvent(e);
            break; }
        case INFO_MusicCatalogTrackAdded: {
            if (m_inUpdateSong) {
                MusicCatalogTrackAddedEvent *mcta =
                                             (MusicCatalogTrackAddedEvent *)e;
                m_newItem = (PlaylistItem *)mcta->Item();
                m_newArtist = (ArtistList *)mcta->Artist();
                m_newAlbum = (AlbumList *)mcta->Album();

                delete e;
            }
            else 
                m_context->target->AcceptEvent(e);
            break; }
        case INFO_PlaylistItemUpdated: {
            if (m_acceptItemChanged) {
                PlaylistItemUpdatedEvent *piu = (PlaylistItemUpdatedEvent *)e;
                WriteMetaDataToDatabase(piu->Item()->URL().c_str(), 
                                        (MetaData)piu->Item()->GetMetaData());

                delete piu->Item();
                m_itemWaitCount--;
            }
            break; }
        case INFO_SearchMusicDone: {
            m_database->Sync();
            string info = "Pruning the Music Catalog Database...";
            m_context->target->AcceptEvent(new BrowserMessageEvent(info.c_str()));
            PruneDatabase();
            info = "Regenerating the Music Catalog Database...";
            m_context->target->AcceptEvent(new BrowserMessageEvent(info.c_str()));
            RePopulateFromDatabase();
            info = "Sorting the Music Catalog Database...";
            m_context->target->AcceptEvent(new BrowserMessageEvent(info.c_str()));
            Sort();
            m_context->target->AcceptEvent(new Event(INFO_SearchMusicDone));
            delete e;
            break;
        } 
    }
    return 0; 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -