⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mbcd.cpp

📁 FreeAMP(MP3播放)程序源代码-用来研究MP3解码
💻 CPP
字号:
/*____________________________________________________________________________
    
    FreeAmp - The Free MP3 Player

    Portions Copyright (C) 2000 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: mbcd.cpp,v 1.14 2001/02/21 04:19:08 ijr Exp $
____________________________________________________________________________*/

#include <assert.h>
#include <string>
#include <errno.h>

using namespace std;

#include "config.h"
#include "errors.h"
#include "utility.h"

#include "mbcd.h"
#include "player.h"

const int iDataLen = 256;

#define DB Debug_v("%d", __LINE__);

extern "C"
{
   MetaDataFormat *Initialize(FAContext* context)
   {
      return new MusicBrainzCD(context);
   }
}

MusicBrainzCD::MusicBrainzCD(FAContext* context)
              :MetaDataFormat(context)
{
    o = NULL;
    m_nextTrack = -1;
	m_notFoundDiskId[0] = 0;
}

MusicBrainzCD::~MusicBrainzCD()
{
}

bool MusicBrainzCD::ReadMetaData(const char* url, MetaData* metadata)
{
    int  track, numTracks, i;
    char data[iDataLen], *ptr;

    assert(url);
    assert(metadata);

    if(!url || !metadata)
       return false;

    char *ext = strrchr(url, '.');
    if (!ext)
       return false;

    if (strncasecmp(".CDA", ext, 4))
       return false;

    ptr = strrchr(url, '/');
    if (ptr == NULL)
       return false;

    m_mutex.Acquire();

    track = atoi(ptr + 1);
    if (track != m_nextTrack)
    {
        if (o)
          mb_Delete(o);

        o = mb_New();
        mb_UseUTF8(o, 0);
        if (!LookupCD())
        {
           mb_Delete(o);
           o = NULL; 
           m_nextTrack = 2;
           m_mutex.Release();
           return false;
        }
        m_nextTrack = 1;
    }
    if (o == NULL)
    {
       m_mutex.Release();
       return false;
    }

    mb_GetResultData(o, MB_GetNumTracks, data, iDataLen);
    numTracks = atoi(data);

    mb_Select(o, MB_SelectAlbum);  

    mb_GetResultData(o, MB_GetAlbumName, data, iDataLen);
    metadata->SetAlbum(data);

    if (mb_DoesResultExist(o, MB_GetArtistName))
    {
        mb_GetResultData(o, MB_GetArtistName, data, iDataLen);
        metadata->SetArtist(data);

        mb_Select(o, MB_SelectFirstTrack);
        for(i = 0; i < track - 1; i++)
            mb_Select(o, MB_SelectNextTrack);

        mb_GetResultData(o, MB_GetTrackName, data, iDataLen);
        metadata->SetTitle(data);
    }
    else
    {
        mb_Select(o, MB_SelectFirstTrack);
        for(i = 0; i < track - 1; i++)
            mb_Select(o, MB_SelectNextTrack);

        mb_GetResultData(o, MB_GetArtistName, data, iDataLen);
        metadata->SetArtist(data);
        mb_GetResultData(o, MB_GetTrackName, data, iDataLen);
        metadata->SetTitle(data);
    }

    metadata->SetTrack(track);
    metadata->SetTime(m_trackLens[track - 1]);

    if (track == numTracks)
    {
       mb_Delete(o);
       o = NULL;
       m_nextTrack = -1;
    }
    m_nextTrack++;

    m_mutex.Release();

    return true;
}

bool MusicBrainzCD::LookupCD(void)
{
    char          error[iDataLen], trackLens[1024], *ptr, *result;
    char          diskId[64];
    int           ret;
    unsigned short  proxyPort;
    char         *tempDir = new char[_MAX_PATH];
    uint32        length = _MAX_PATH;
    Database     *db;
    string        rdf, proxyServer;
    char          url[MAX_PATH], hostname[MAX_PATH];
    int           i, port;
    uint32        len = MAX_PATH;
    string        message;

    error[0] = 0;
    m_context->prefs->GetPrefString(kDatabaseDirPref, tempDir, &length);

    string database = string(tempDir) + string(DIR_MARKER_STR) +
                      string("mbcd");

    m_context->prefs->GetPrefString(kCDDevicePathPref, tempDir, &length);
    mb_SetDevice(o, tempDir);

    // Parse the musicbrainz server from the preference
    m_context->prefs->GetPrefString(kMBServerPref, url, &len);
    i = sscanf(url, " http://%[^:/]:%d", hostname, &port);
    if (i == 0)
        i = sscanf(url, " %[^:/]:%d", hostname, &port);
    if (i < 2)
        port = MUSICBRAINZ_PORT;
    if (i < 1)
        strcpy(hostname, MUSICBRAINZ_SERVER);

    mb_SetServer(o, hostname, port);
    if (GetProxySettings(m_context, proxyServer, proxyPort))
       mb_SetProxy(o, (char *)proxyServer.c_str(), proxyPort);

    ret = mb_Query(o, MB_GetCDTOC);
    if (!ret)
    {
       mb_GetQueryError(o, error, iDataLen);
       message = error;
       m_context->target->AcceptEvent(new BrowserMessageEvent(message));
       return false;
    }

    if (!mb_Select(o, MB_SelectTopLevel))
    {
       return false;
    }
    if (!mb_GetResultData(o, MB_LocalGetTrackLengths, trackLens, 1024))
    {
       mb_GetQueryError(o, error, iDataLen);
       return false;
    }

    m_trackLens.clear();
    for(ptr = strtok(trackLens, " "); ptr; ptr = strtok(NULL, " "))
       m_trackLens.push_back(atoi(ptr));
    mb_GetResultData(o, MB_LocalGetId, diskId, 64);

	if (strcmp(diskId, m_notFoundDiskId) == 0)
    {
	   time_t t;

	   time(&t);
	   if (t < m_notFoundDiskIdExpire)
          return false;

	   m_notFoundDiskId[0] = 0;
    }

    db = new Database(database.c_str());
    delete [] tempDir;

    if (ReadFromCache(db, diskId, m_trackLens, rdf) &&
        mb_SetResultRDF(o, (char *)rdf.c_str()))
    { 
        message = "Retrieved CD from local cache.";
        m_context->target->AcceptEvent(new  BrowserMessageEvent(message));
    }
    else
    {
        message = "Sending CD lookup query to MusicBrainz...";
        m_context->target->AcceptEvent(new BrowserMessageEvent(message));
        ret = mb_Query(o, MB_GetCDInfo);
        if (!ret)
        {
           mb_GetQueryError(o, error, iDataLen);
           message = error;
           m_context->target->AcceptEvent(new BrowserMessageEvent(message));
           delete db;
           return false;
        }
    
        if (mb_GetNumItems(o) == 0)
        {
           char url[MAX_PATH];

		   // Due to a shortcoming in the design of the metadata stuff, the
		   // player will continue to ask for more tracks even after a CD has
		   // not been found. In order to avoid hitting the server for each track
		   // we'll keep the diskid around and if subsequently we're asked for a
		   // query on the same CD, we will just skip the query. A timeout value
		   // is associated with the not found cd id, so that if the cd info 
		   // is entered into MB, and the user updates the cd we force the query
		   // to the server after the timeout (suggested: 60 seconds)
		   strcpy(m_notFoundDiskId, diskId);
		   time(&m_notFoundDiskIdExpire);
		   m_notFoundDiskIdExpire += 60;

           mb_GetWebSubmitURL(o, url, MAX_PATH);
           message = "CD not found.";
           m_context->target->AcceptEvent(new BrowserMessageEvent(message));
           m_context->target->AcceptEvent(new CDNotFoundEvent(url));
           delete db;
           return false;
        }  
    
        ret = mb_GetResultRDFLen(o) + 1;
        result = new char[ret];
        if (mb_GetResultRDF(o, result, ret))
        {
            message = "Found CD.";
            m_context->target->AcceptEvent(new BrowserMessageEvent(message));
            WriteToCache(db, diskId, m_trackLens, result); 
        }
        else
        {
            message = "Query failed.";
            m_context->target->AcceptEvent(new BrowserMessageEvent(message));
        }
        delete result;
    }
    delete db;

    return true;
}


bool MusicBrainzCD::WriteMetaData(const char* url, const MetaData& metadata)
{
    bool result = false;
    return result;
}

void MusicBrainzCD::WriteToCache(Database *db, char *diskId, 
                                 vector<int> &trackLens, char *rdf)
{
    char                  *data;
    vector<int>::iterator  i;

    if (db->Exists(diskId))
    {
       db->Remove(diskId);
    }

    data = new char[strlen(diskId) + strlen(rdf) + 1024];
    data[0] = 0;
    for(i = trackLens.begin(); i != trackLens.end(); i++)
       sprintf(data + strlen(data), "%d ", *i); 

    sprintf(data + strlen(data) - 1, "%s", rdf); 
    db->Insert(diskId, data);
    delete data;
}

bool MusicBrainzCD::ReadFromCache(Database *db, char *diskId, 
                                 vector<int> &trackLens, string &rdf)
{
    char *data, temp[1024], *ptr;
    bool  ret = false;

    if (db->Exists(diskId))
    {
        data = db->Value(diskId);    

        if (sscanf(data, "%[^<]", temp) > 0)
        {
           trackLens.clear();
           for(ptr = strtok(temp, " "); ptr; ptr = strtok(NULL, " "))
              trackLens.push_back(atoi(ptr));

           ptr = strchr(data, '<');
           if (ptr)
           {
               rdf = string(ptr);
               ret = true;
           }
        }

        delete data;
    }

    return ret;
}

⌨️ 快捷键说明

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