📄 downloadmanager.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: downloadmanager.cpp,v 1.40 2001/02/21 04:19:08 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 "config.h"
#include <assert.h>
#include "downloadmanager.h"
#include "musiccatalog.h"
#if defined(unix) || defined(__BEOS__) || defined(_BSD_SOURCE)
#define SOCKET int
#endif
#if !defined(WIN32)
#include <sys/time.h>
#include <strstream>
typedef ostrstream ostringstream;
#else
#include <sstream>
#endif
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <iostream>
#include <algorithm>
#include <fstream>
#if defined (unix) || defined(_BSD_SOURCE)
#include <arpa/inet.h>
#define closesocket(x) close(x)
#ifndef O_BINARY
#define O_BINARY 0
#endif
#endif
using namespace std;
#include "facontext.h"
#include "errors.h"
#include "registrar.h"
#include "utility.h"
#include "eventdata.h"
#ifdef __QNX__
#include <strings.h>
#endif
DownloadManager::DownloadManager(FAContext* context)
{
m_context = context;
m_current = 0;
m_downloadsPaused = true;
m_downloadIndex = -1;
m_exit = false;
Registrar registrar;
registrar.SetSubDir("plugins");
registrar.SetSearchString("*.dlf");
registrar.InitializeRegistry(&m_formatRegistry, context->prefs);
const RegistryItem* module = NULL;
DownloadFormat* dlf = NULL;
int32 i = 0;
while((module = m_formatRegistry.GetItem(i++)))
{
dlf = (DownloadFormat*) module->InitFunction()(m_context);
if(dlf)
{
DownloadFormatInfo dlfi;
uint32 index = 0;
// error != kError_NoMoreFormats
while(IsntError(dlf->GetSupportedFormats(&dlfi, index++)))
{
dlfi.SetRef(dlf);
m_formats.push_back(new DownloadFormatInfo(dlfi));
}
}
}
LoadResumableDownloadItems();
char path[MAX_PATH];
uint32 length = sizeof(path);
context->prefs->GetPrefString(kInstallDirPref, path, &length);
strcat(path, "\\DownloadLog.txt");
m_runDownloadThread = true;
m_downloadThread = Thread::CreateThread();
if(m_downloadThread)
{
m_downloadThread->Create(download_thread_function, this, true);
}
}
DownloadManager::~DownloadManager()
{
uint32 index = 0;
uint32 size = 0;
DownloadItem* item = NULL;
m_exit = true;
m_runDownloadThread = false;
m_queueSemaphore.Signal();
m_quitMutex.Acquire();
SaveResumableDownloadItems();
size = m_itemList.size();
for(index = 0; index < size; index++)
{
item = m_itemList[index];
if(item)
{
if(item->GetState() == kDownloadItemState_Cancelled)
{
CleanUpDownload(item);
}
delete item;
}
}
size = m_formats.size();
for(index = 0; index < size; index++)
{
delete m_formats[index]->GetRef();
delete m_formats[index];
}
if(m_downloadThread)
{
delete m_downloadThread;
}
//delete m_debug;
}
// Functions for adding items to Download Manager
// Adding an item implicitly queues it for
// downloading.
Error DownloadManager::AddItem(const char* url, const char* filename)
{
Error result = kError_InvalidParam;
assert(url);
if(url)
{
result = kError_OutOfMemory;
if(!filename)
{
filename = strrchr(url, '/');
if(filename)
filename++;
else
filename = url;
}
DownloadItem* item = new DownloadItem(url, filename);
if(item)
{
item->SetNormalDownload();
result = AddItem(item);
}
}
return result;
}
Error DownloadManager::AddItem(DownloadItem* item)
{
Error result = kError_InvalidParam;
vector<DownloadItem*>::iterator j;
m_mutex.Acquire();
assert(item);
if(item)
{
for(j = m_itemList.begin(); j != m_itemList.end(); j++)
if ((*j)->SourceURL() == item->SourceURL())
break;
if (j == m_itemList.end())
{
m_itemList.push_back(item);
SendItemAddedMessage(item);
QueueDownload(item);
}
result = kError_NoErr;
}
m_mutex.Release();
return result;
}
Error DownloadManager::AddItems(vector<DownloadItem*>* list)
{
Error result = kError_InvalidParam;
vector<DownloadItem*>::iterator i, j;
m_mutex.Acquire();
assert(list);
if(list)
{
for(i = list->begin(); i != list->end(); i++)
{
for(j = m_itemList.begin(); j != m_itemList.end(); j++)
if ((*i)->SourceURL() == (*j)->SourceURL())
break;
if (j == m_itemList.end())
{
m_itemList.push_back(*i);
SendItemAddedMessage(*i);
QueueDownload(*i);
}
}
result = kError_NoErr;
}
m_mutex.Release();
return result;
}
// Changes item state to queued if it is cancelled or error.
// This will indicate to the download thread that it should
// attempt to retrieve this item. Has no effect if the item's
// state is Done, or Downloading.
Error DownloadManager::QueueDownload(DownloadItem* item,
bool bDownloadNow)
{
Error result = kError_InvalidParam;
unsigned int index;
assert(item);
if(item)
{
if(item->GetState() != kDownloadItemState_Downloading &&
item->GetState() != kDownloadItemState_Done)
{
item->SetState(kDownloadItemState_Queued);
SendStateChangedMessage(item);
if (m_downloadsPaused && bDownloadNow)
for(index = 0; index < m_itemList.size(); index++)
if (m_itemList[index] == item)
{
m_downloadIndex = index;
break;
}
m_queueSemaphore.Signal();
result = kError_NoErr;
}
}
return result;
}
Error DownloadManager::QueueDownload(uint32 index)
{
return QueueDownload(ItemAt(index));
}
// Changes item state to cancelled if it is queued or downloading.
// If allowResume is true then data is retained for later download.
// Has no effect if the item's state is Done, Cancelled, or Error.
Error DownloadManager::CancelDownload(DownloadItem* item, bool allowResume)
{
Error result = kError_InvalidParam;
assert(item);
if(item)
{
if(item->GetState() == kDownloadItemState_Downloading ||
item->GetState() == kDownloadItemState_Queued ||
item->GetState() == kDownloadItemState_Paused)
{
if(!allowResume)
{
item->SetState(kDownloadItemState_Cancelled);
}
else
{
item->SetState(kDownloadItemState_Paused);
}
SendStateChangedMessage(item);
result = kError_NoErr;
}
}
return result;
}
Error DownloadManager::CancelDownload(uint32 index, bool allowResume)
{
return CancelDownload(ItemAt(index), allowResume);
}
// File Format support
Error DownloadManager::GetSupportedDownloadFormats(DownloadFormatInfo* format,
uint32 index)
{
Error result = kError_InvalidParam;
assert(format);
if(format)
{
result = kError_NoMoreFormats;
uint32 numFormats = m_formats.size();
if(index < numFormats)
{
result = kError_NoErr;
*format = *m_formats[index];
}
}
return result;
}
Error DownloadManager::ReadDownloadFile(char* url,
vector<DownloadItem*>* items)
{
Error result = kError_InvalidParam;
assert(url);
if(url)
{
// find a suitable plugin
result = kError_FormatNotSupported;
char* extension = strrchr(url, '.');
if(extension)
{
extension++;
uint32 numFormats = m_formats.size();
for(uint32 index = 0; index < numFormats; index++)
{
DownloadFormatInfo* format = m_formats[index];
if(!strcmp(extension, format->GetExtension()))
{
bool addToInternalList = false;
if(!items)
{
items = new vector<DownloadItem*>;
addToInternalList = true;
}
result = format->GetRef()->ReadDownloadFile(url,
items);
if(addToInternalList)
{
AddItems(items);
delete items;
}
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -