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

📄 downloadmanager.cpp

📁 FreeAMP(MP3播放)程序源代码-用来研究MP3解码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*____________________________________________________________________________
	
	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 + -