📄 apsinterface.cpp
字号:
/*________________________________________________________________________
FreeAmp - The Free MP3 Player
Portions Copyright (C) 2000 Relatable
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: apsinterface.cpp,v 1.45 2001/03/06 04:29:20 ijr Exp $
____________________________________________________________________________*/
///////////////////////////////////////////////////////////////////
// Copyright 1999 Relatable, LLC. All Rights Reserved
// Programed By: Sean Ward
// Description: Interface declaration file for Relatable APS system
// Date: 12/13/1999
// Modification History:
// 12/13/1999 : First Created
// Sometime: Stuff
// 07/25/2000 : Lots of stuff/cruft/hallucinations cleaned up
///////////////////////////////////////////////////////////////////
#ifdef WIN32
#pragma warning(disable:4786)
#endif
#include "aps.h"
#include "apsplaylist.h"
#include "apsmetadata.h"
#include "uuid.h"
#include <strstream>
#ifdef WIN32
#include "wincomsocket.h"
#else
#include "comsocket.h"
#endif
#include "config.h"
#include "mutex.h"
#include "semaphore.h"
#include "YPClient.h"
#include "apsutility.h"
#include "apsconvert.h"
#include <math.h>
#include <musicbrainz/mb_c.h>
#include "utility.h"
#ifndef WIN32
#define ios_base ios
#endif
const int nAPSYPPort = 4444;
const int nAPSSigPort = 4445;
APSInterface::APSInterface(FAContext *context, const char* pIP,
const char *pSigIP)
{
//srand((unsigned)time(NULL)); // comment out if already inited elsewhere
m_strIP = pIP;
m_sigIP = pSigIP;
m_pMutex = new Mutex();
m_pSema = new Semaphore(MAX_METADATAQUERIES);
m_pProfileMap = new map<string, string>;
m_pActiveProfiles = new vector<string>;
m_bRelatableOn = true;
m_pLogFile = NULL;
m_context = context;
m_profilePath = string(FreeampDir(m_context->prefs));
string savedProfiles = m_profilePath + string(DIR_MARKER_STR) +
string("profiles.txt");
LoadProfileMap(savedProfiles.c_str()); // could be made into a configurable option
m_pYpClient = new YPClient;
m_pYpClient->SetAddress(m_strIP.c_str(), nAPSYPPort);
m_nMetaFailures = 0;
if (!m_strCurrentProfile.empty()) {
ChangeProfile(m_strCurrentProfile.c_str());
//SyncLog();
}
}
APSInterface::~APSInterface()
{
string savedProfiles = m_profilePath + string(DIR_MARKER_STR) +
string("profiles.txt");
WriteProfileMap(savedProfiles.c_str());
if (m_pYpClient != NULL)
{
delete m_pYpClient;
m_pYpClient = NULL;
}
if (m_pMutex != NULL)
{
delete m_pMutex;
m_pMutex = NULL;
}
if (m_pSema != NULL)
{
delete m_pSema;
m_pSema = NULL;
}
if (m_pLogFile != NULL)
{
m_pLogFile->close();
delete m_pLogFile;
m_pLogFile = NULL;
}
if (m_pProfileMap != NULL)
{
delete m_pProfileMap;
m_pProfileMap = NULL;
}
if (m_pActiveProfiles != NULL)
{
delete m_pActiveProfiles;
m_pActiveProfiles = NULL;
}
}
void APSInterface::SetProxy(string strAddr, int nPort)
{
m_strProxyAddr = strAddr;
m_nProxyPort = nPort;
if (m_pYpClient)
m_pYpClient->SetProxy(m_strProxyAddr, m_nProxyPort);
}
int APSInterface::APSFillMetaData(APSMetaData* pmetaData)
{
if (pmetaData == NULL)
return APS_PARAMERROR;
m_pSema->Wait();
musicbrainz_t o;
int ret;
char *args[20];
char temp[255], guid[40], url[MAX_PATH];
char hostname[MAX_PATH], file[MAX_PATH];
int i, port;
uint32 len = MAX_PATH;
BitprintInfo info;
memset(args, 0, sizeof(args));
// 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);
o = mb_New();
// Calculate the bitzi bitprint for this file.
len = MAX_PATH;
URLToFilePath((char *)pmetaData->Filename().c_str(), file, &len);
mb_CalculateBitprint(o, file, &info);
mb_UseUTF8(o, 0);
mb_SetServer(o, hostname, port);
if (m_strProxyAddr.size() > 7)
mb_SetProxy(o, (char *)m_strProxyAddr.c_str(), m_nProxyPort);
uuid_ascii((unsigned char*)pmetaData->GUID().c_str(), guid);
string guidMapping = m_profilePath + string(DIR_MARKER_STR) +
string("guid_mapping.txt");
FILE *guidLogfile = fopen(guidMapping.c_str(), "a+");
fprintf(guidLogfile, "%s\t%s\n", pmetaData->Filename().c_str(),
guid);
fclose(guidLogfile);
args[0] = strdup(pmetaData->Title().c_str());
args[1] = strdup(pmetaData->Artist().c_str());
args[2] = strdup(pmetaData->Album().c_str());
sprintf(temp, "%d", pmetaData->Track());
args[3] = strdup(temp);
args[4] = strdup(guid);
args[5] = strdup(pmetaData->Filename().c_str());
sprintf(temp, "%d", pmetaData->Year());
args[6] = strdup(temp);
args[7] = strdup(pmetaData->Genre().c_str());
args[8] = strdup(pmetaData->Comment().c_str());
// These are the bitzi bitpint metadata items
args[9] = strdup(info.bitprint);
args[10] = strdup(info.first20);
sprintf(temp, "%d", info.length);
args[11] = strdup(temp);
if (info.audioSha1)
{
args[12] = strdup(info.audioSha1);
sprintf(temp, "%d", info.duration);
args[13] = strdup(temp);
sprintf(temp, "%d", info.samplerate);
args[14] = strdup(temp);
sprintf(temp, "%d", info.bitrate);
args[15] = strdup(temp);
sprintf(temp, "%d", info.stereo);
args[16] = strdup(temp);
sprintf(temp, "%d", info.vbr);
args[17] = strdup(temp);
args[18] = NULL;
}
else
{
args[12] = NULL;
}
ret = mb_QueryWithArgs(o, MB_ExchangeMetadata, args);
for(i = 0; i < 11; i++)
if (args[i])
free(args[i]);
if (!ret)
{
m_pSema->Signal();
return APS_NETWORKERROR;
}
// This query should always return one item
if (mb_GetNumItems(o) == 0)
{
m_pSema->Signal();
return APS_GENERALERROR;
}
// Now start the data extraction process.
// Select the album context of the exchanged data
mb_Select(o, MB_SelectExchangedAlbum);
if (mb_GetResultData(o, MB_GetAlbumName, temp, 255))
pmetaData->SetAlbum(temp);
// Select the main context of the exchanged data
mb_Select(o, MB_SelectExchangedData);
if (mb_GetResultData(o, MB_GetArtistName, temp, 255))
pmetaData->SetArtist(temp);
if (mb_GetResultData(o, MB_GetTrackName, temp, 255))
pmetaData->SetTitle(temp);
if (mb_GetResultData(o, MB_GetGenre, temp, 255))
pmetaData->SetGenre(temp);
if (mb_GetResultData(o, MB_GetDescription, temp, 255))
pmetaData->SetComment(temp);
pmetaData->SetYear(mb_GetResultInt(o, MB_GetYear));
pmetaData->SetTrack(mb_GetResultInt(o, MB_GetTrackNum));
pmetaData->SetLength(mb_GetResultInt(o, MB_GetDuration));
mb_Delete(o);
m_pSema->Signal();
return APS_NOERROR;
}
int APSInterface::APSGetSoundsLike(APSPlaylist *pSeedList,
APSPlaylist *pReturnList,
int nMaxItems)
{
if ((pSeedList == NULL) || (pReturnList == NULL))
return APS_PARAMERROR;
m_pMutex->Acquire();
string strUID = "";
if (!m_strCurrentProfile.empty())
strUID = (*m_pProfileMap)[m_strCurrentProfile];
if (strUID.empty())
strUID = "NOT_OPTED_IN1111"; // 16 char aggregate query id
int nRes = m_pYpClient->SoundsLike(*pReturnList, *pSeedList,
m_strCollectionID);
m_pMutex->Release();
return nRes;
}
int APSInterface::APSGetPlaylist(APSPlaylist* pPlayList,
APSPlaylist* pResultList, int nMaxItems,
bool bLocalOnly)
{
if ((pPlayList == NULL) || (pResultList == NULL))
return APS_PARAMERROR;
m_pMutex->Acquire();
string strUID = "";
if (!m_strCurrentProfile.empty())
strUID = (*m_pProfileMap)[m_strCurrentProfile];
if (strUID.empty())
strUID = "NOT_OPTED_IN1111"; // 16 char aggregate query id
int nRes = m_pYpClient->GeneratePlayList(*pResultList, *pPlayList,
nMaxItems, bLocalOnly, strUID,
m_strCollectionID);
m_pMutex->Release();
return nRes;
}
int APSInterface::APSSubmitPlaylist(APSPlaylist* pPlayList)
{
if (pPlayList == NULL)
return APS_PARAMERROR;
m_pMutex->Acquire();
string strUID = "";
if (!m_strCurrentProfile.empty())
strUID = (*m_pProfileMap)[m_strCurrentProfile];
if (strUID.empty())
strUID = "NOT_OPTED_IN1111"; // 16 char aggregate query id
int nRes = m_pYpClient->SubmitPlaylist(*pPlayList, strUID);
m_pMutex->Release();
return nRes;
}
void APSInterface::WriteToLog(const string& strGUID, int nEventType)
{
if (m_strCurrentProfile.empty())
return; // if no active profile, don't log anything
m_pMutex->Acquire();
if (m_pLogFile == NULL)
{
// name the logfile after the profile alias
string logfilename = m_profilePath + string(DIR_MARKER_STR) +
m_strCurrentProfile;
m_pLogFile = new fstream(logfilename.c_str(),
ios_base::out | ios_base::app);
}
time_t currenttime;
time(¤ttime);
*m_pLogFile << currenttime << " " << strGUID << " " << nEventType << endl;
m_pMutex->Release();
}
int APSInterface::ChangeProfile(const char *pczUserName)
{
if (pczUserName == NULL)
return APS_PARAMERROR;
if (m_pProfileMap->empty())
return APS_PARAMERROR;
map<string, string>::iterator i;
i = m_pProfileMap->find(pczUserName);
if (i != m_pProfileMap->end())
{
if (m_pLogFile != NULL)
{
if (m_pLogFile->is_open())
m_pLogFile->close();
delete m_pLogFile;
m_pLogFile = NULL;
}
m_strCurrentProfile = pczUserName;
CombineProfile(pczUserName);
string logfilename = m_profilePath + string(DIR_MARKER_STR) +
string(pczUserName);
m_pLogFile = new fstream(logfilename.c_str(),
ios_base::out | ios_base::app);
string savedProfiles = m_profilePath + string(DIR_MARKER_STR) +
string("profiles.txt");
WriteProfileMap(savedProfiles.c_str());
return APS_NOERROR;
}
else
return APS_PARAMERROR;
}
int APSInterface::APSGetStreams(vector<pair<string, string> >* pResultList)
{
if (pResultList == NULL)
return APS_PARAMERROR;
m_pMutex->Acquire();
string strUID = "";
if (!m_strCurrentProfile.empty())
strUID = (*m_pProfileMap)[m_strCurrentProfile];
if (strUID.empty())
strUID = "NOT_OPTED_IN1111"; // 16 char aggregate query id
int nRes = m_pYpClient->GetStreams(*pResultList, strUID, m_strCollectionID);
fstream fout("test.txt", ios_base::in | ios_base::out | ios_base::app);
fout << "GetStream returned: " << nRes << " and filled in " <<
pResultList->size() << " items:" << endl;
vector<pair<string, string> >::iterator i;
for (i = pResultList->begin(); i != pResultList->end(); i++)
{
fout << (*i).first << " : " << (*i).second << endl;
}
fout.close();
m_pMutex->Release();
return nRes;
}
int APSInterface::CreateProfile(const char *pczNewName)
{
if (pczNewName == NULL)
return APS_PARAMERROR;
m_pMutex->Acquire();
if ((m_pProfileMap->empty()) ||
(m_pProfileMap->end() == m_pProfileMap->find(pczNewName)))
{
string strGUID = "";
int nRes = m_pYpClient->GetGUID(strGUID, 0);
if (nRes == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -