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

📄 player.cpp

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

        Portions Copyright (C) 1998-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: player.cpp,v 1.259 2001/03/02 04:16:57 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 <iostream>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h> 
#ifdef WIN32
#include <direct.h>
#define MKDIR(z) mkdir(z)
#else
#define MKDIR(z) mkdir(z, 0755)
#endif

#ifdef __QNX__
#include <strings.h>
#endif

#include <set>

#include "config.h"
#include "event.h"
#include "lmc.h"
#include "player.h"
#include "thread.h"
#include "debug.h"
#include "ui.h"
#include "queue.h"
#include "semaphore.h"
#include "eventdata.h"
#include "registrar.h"
#include "preferences.h"
#include "properties.h"
#include "facontext.h"
#include "log.h"
#include "pmo.h"
#include "utility.h"
#include "downloadmanager.h"
#include "timer.h"

#define DB Debug_v("%s:%d\n", __FILE__, __LINE__);

Player   *Player::m_thePlayer = NULL;

const char *szPlaylistExt = ".M3U";
const char *themeExtension = "fat";

#define SEND_NORMAL_EVENT(e) { Event *ev = new Event(e); GetUIManipLock();    \
                               SendToUI(ev); ReleaseUIManipLock(); delete ev; \
                             }

Player *
Player::
GetPlayer(FAContext *context)
{
    if (m_thePlayer == NULL)
        m_thePlayer = new Player(context);
    return m_thePlayer;
}

Player::
Player(FAContext *context) : EventQueue()
{
    m_context = context;
    m_context->player = this;

    m_APSInterface = new APSInterface(context);
    m_context->aps = m_APSInterface;

    bool useProxy = false;
    m_context->prefs->GetPrefBoolean(kUseProxyPref, &useProxy);
    if (useProxy)
    {
       uint32 size = 1024;
       char *buffer = (char *)malloc(size);

       if (kError_BufferTooSmall == m_context->prefs->GetPrefString(
                                                 kProxyHostPref, buffer, &size))
       {
           buffer = (char *)realloc(buffer, size);
           m_context->prefs->GetPrefString(kProxyHostPref, buffer, &size);
       }
   
       char *port = strrchr(buffer, ':');
       if (port) {
           *port = '\0';
           port++;
       }

       string proxyAddr = string(buffer, strlen(buffer) + 1);
       int nPort = 80;
       if (port && *port)
           nPort = atoi(port);

       free(buffer);
       m_APSInterface->SetProxy(proxyAddr.c_str(), nPort);
    }
    else
       m_APSInterface->SetProxy("", 0);

    m_signatureThread = NULL;
    m_bKillSignature = false;

    // cout << "Creating player..." << endl;
    m_eventSem = new Semaphore();
    m_eventQueue = new Queue < Event * >();
    // cout << "Created queue" << endl;
    m_eventServiceThread = NULL;
    // cout << "Started event thread" << endl;
    m_uiList = new vector < UserInterface * >;
    // cout << "Created Lists" << endl;
    m_uiManipLock = new Mutex();
    m_lmcMutex = new Mutex();
    m_pmiMutex = new Mutex();
    m_pmoMutex = new Mutex();
    m_uiMutex = new Mutex();
    m_sigStopMutex = new Mutex();
    // cout << "Created mutex" << endl;
    m_imQuitting = 0;
    m_quitWaitingFor = 0;
    m_plm = new PlaylistManager(m_context);
    m_playerState = PlayerState_Stopped;

    m_lmcRegistry = NULL;
    m_pmiRegistry = NULL;
    m_pmoRegistry = NULL;
    m_uiRegistry = NULL;

    m_lmcExtensions = NULL;
    m_pmiProtocols = NULL;

    m_browserUI = NULL;
    m_downloadUI = NULL;

    m_sigspmo = NULL;
    m_pmo = NULL;
    m_lmc = NULL;
    m_ui = NULL;

    m_argUIList = new vector < char *>();

    m_argc = 0;
    m_argv = NULL;
    m_pTermSem = NULL;

    m_didUsage = false;
    m_autoplay = true;

    m_props.RegisterPropertyWatcher("pcm_volume", (PropertyWatcher *) this);

    m_context->plm = m_plm;
    m_context->props = &m_props;
    m_context->target = (EventQueue *) this;
    m_context->timerManager = new TimerManager();

    // add timer for checking CDs
    // this should be used only if there is no way to get notifications
    // from the OS since polling is inefficient

#ifndef WIN32
    m_cdTimer = NULL;

    bool pollCD = false;
    m_context->prefs->GetPrefBoolean(kCheckCDAutomaticallyPref, &pollCD);

    if (pollCD)
        m_context->timerManager->StartTimer(&m_cdTimer, cd_timer, 5, this);

    m_cdTimerActive = pollCD;

#endif
    // make sure the db dir exists so we have a place to store our 
    // stuff

    char* tempDir = new char[_MAX_PATH];
    uint32 length = _MAX_PATH;
    struct stat st;

    m_context->prefs->GetPrefString(kDatabaseDirPref, tempDir, &length);

    if(-1 == stat(tempDir, &st))
    {
        MKDIR(tempDir);
    }

    m_musicCatalog = new MusicCatalog(m_context);
    m_context->catalog = m_musicCatalog;

    string freeampdir = tempDir;
    freeampdir += DIR_MARKER_STR;
    freeampdir += "metadatabase";
    m_musicCatalog->SetDatabase(freeampdir.c_str());

    // make sure the music dir exists so we have a place to store our 
    // stuff

    length = _MAX_PATH;
    m_context->prefs->GetPrefString(kSaveMusicDirPref, tempDir, &length);

    if(-1 == stat(tempDir, &st))
    {
        MKDIR(tempDir);
    }

    delete [] tempDir;
    m_dlm = new DownloadManager(m_context);
    m_context->downloadManager = m_dlm;

    m_eqEnabled = false;
    memset(m_eqValues, 0, sizeof(m_eqValues));

    // Add timer for sync-ing the log to the relatable servers
    // only works if a profile is currently active
    m_context->timerManager->StartTimer(&m_syncTimer, synclog_timer, 180, this);
}

#define TYPICAL_DELETE(x) /*printf("deleting...\n");*/ if (x) { delete x; x = NULL; }

Player::
~Player()
{
#ifndef WIN32
    m_context->timerManager->StopTimer(m_cdTimer);
#endif
    m_context->timerManager->StopTimer(m_syncTimer);

    TYPICAL_DELETE(m_dlm);

    TYPICAL_DELETE(m_pTermSem);

    if(m_argUIList)
    {
        vector<char*>::iterator i = m_argUIList->begin();

        for (; i != m_argUIList->end(); i++)
            delete [] *i; 

        delete m_argUIList;

        m_argUIList = NULL;
    }

    if(m_eventServiceThread)
    {
        m_eventServiceThread->Join();
        delete    m_eventServiceThread;

        m_eventServiceThread = NULL;
    }

    KillSigThread(NULL);

    if(m_pmo)
    {
        m_pmo->Pause();
        delete    m_pmo;

        m_pmo = NULL;
    }

    TYPICAL_DELETE(m_eventSem);
    TYPICAL_DELETE(m_eventQueue);

    // Delete CIOs
    if(m_uiList)
    {
        vector<UserInterface *>::iterator i = m_uiList->begin();

        for (; i != m_uiList->end(); i++)
            delete *i; 
        delete m_uiList;

        m_uiList = NULL;
    }

    TYPICAL_DELETE(m_musicCatalog);
    TYPICAL_DELETE(m_APSInterface);
    TYPICAL_DELETE(m_uiManipLock);
    TYPICAL_DELETE(m_lmcMutex);
    TYPICAL_DELETE(m_pmiMutex);
    TYPICAL_DELETE(m_pmoMutex);
    TYPICAL_DELETE(m_uiMutex);

    TYPICAL_DELETE(m_lmcRegistry);
    TYPICAL_DELETE(m_pmiRegistry);
    TYPICAL_DELETE(m_pmoRegistry);
    TYPICAL_DELETE(m_uiRegistry);

    map<string, RegistryItem *>::iterator i = m_lmcExtensions->begin();
    for (; i != m_lmcExtensions->end(); i++)
        delete (*i).second;
    TYPICAL_DELETE(m_lmcExtensions);

    map<string, RegistryItem *>::iterator j = m_pmiProtocols->begin();
    for (; j != m_pmiProtocols->end(); j++)
        delete (*j).second;
    TYPICAL_DELETE(m_pmiProtocols);

    TYPICAL_DELETE(m_context->timerManager);
    TYPICAL_DELETE(m_sigStopMutex);
    TYPICAL_DELETE(m_plm);
}

void      
Player::
SetTerminationSemaphore(Semaphore * pSem)
{
    m_pTermSem = pSem;
}

/*
    return true if parsing was successful, false otherwise. 
*/

typedef char *pchar;

bool      
Player::
SetArgs(int32 argc, char **argv)
{
    bool autoplay = false;

    // remember these guys so we can use them later and elsewhere
    m_argc = argc;
    m_argv = argv;

    m_context->argv = m_argv;
    m_context->argc = m_argc;

    // now parse them and pull out any args we know about
    for (int32 i = 1; i < argc; i++)
    {
        char* arg = argv[i];

        // is this an option?
        if(arg[0] == '-' 
#ifdef WIN32
        	|| arg[0] == '/'
#endif   
			)
        {
            switch(arg[1])
            {
                // print help
                case 'h':
                case 'H':
                case '-':
                    if(!strcasecmp(arg + 1, "help") || !strcasecmp(arg + 2, "help"))
                    {
                        Usage(argv[0]);
                        AcceptEvent(new Event(CMD_QuitPlayer));
                        return true;
                    }
                    break;

                // autoplay
                case 'p':
                case 'P':
                    if(!strcasecmp(arg + 1, "play"))
                        autoplay = true;

                // save streams
                // shuffle
                case 's':
                case 'S':
                    if(!strcasecmp(arg + 1, "save"))
		                m_context->argFlags |= FAC_ARGFLAGS_SAVE_STREAMS;
                    else if(!strcasecmp(arg + 1, "shuffle"))
                        m_plm->SetShuffleMode(true);
                    break;

                case 'i':
                case 'I':
                    if(!strcasecmp(arg + 1, "import"))
                    {
                        uint32 length = _MAX_PATH;
                        char   url[_MAX_PATH];
                        
                        i++;
                        FilePathToURL(argv[i], url, &length);
                        m_context->catalog->AddSong(url);
                        m_plm->AddItem(url);
                    }
                    break;

                // set UIs
                case 'u':
                case 'U':
                {
                    if(arg[2] == 'i' || arg[2] == 'I')
                    {
                        char* argUI = NULL;
                        
                        i++;
                        if(i >= argc)
                        {
                            Usage(argv[0]);
                            AcceptEvent(new Event(CMD_QuitPlayer));
                            return false;
                        }

                        arg = argv[i];

                        argUI = new char[strlen(arg) + 1];

                        strcpy(argUI, arg);
                        
                        m_argUIList->push_back(argUI);
                    }

                    break;
                }

                default:
                    break;

            }
        }
        else
        {
            HandleSingleArg(arg);
        }
    }
    
    if(m_autoplay)
    {
        AcceptEvent(new Event(CMD_Play));
    }  

    return true;
}

void Player::HandleSingleArg(char *arg)
{
    char* path = new char[_MAX_PATH];
    char* url = new char[_MAX_PATH];
    char *proto = NULL;

    // is this a URL we know how to handle
    proto = GetProtocol(arg);
    if(IsSupportedProtocol(proto)) 
    {
        m_plm->AddItem(arg);
        delete proto;
    }
    else
    {
#ifdef WIN32
        strcpy(path, arg);

        HANDLE handle;
        WIN32_FIND_DATA data;

        handle = FindFirstFile(arg, &data);

        // find long filename for item and
        // expand wildcards...
        if(handle != INVALID_HANDLE_VALUE)
        {
            do
            {
                char* cp = NULL;
            
                cp = strrchr(path, '\\');

                if(cp)
                    cp++;
                else 
                    cp = path;

                strcpy(cp, data.cFileName);


                // make sure we have an absolute path
                ResolvePath(&path);

                // format this path as a URL
                uint32 length = _MAX_PATH;
                FilePathToURL(path, url, &length);

                // who needs to get this, plm or dlm?
                bool giveToDLM = false;
                bool giveToTheme = false;
                char* extension = NULL;

                extension = strrchr(url, '.');
                if(extension)
                {
                    DownloadFormatInfo dlfi;
                    uint32 i = 0;

                    extension++;

                    while(IsntError(m_dlm->GetSupportedDownloadFormats(&dlfi, i++)))
                    {
                        if(!strcasecmp(extension, dlfi.GetExtension()))
                        {
                            giveToDLM = true;
                            break;
                        }
                    }
                    if (!strcasecmp(extension, themeExtension))
                        giveToTheme = true; 
                }

⌨️ 快捷键说明

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