Logo Search packages:      
Sourcecode: zinf version File versions  Download package

cdpmo.cpp

/*____________________________________________________________________________
        
        Zinf - Zinf Is Not FreeA*p (The Free MP3 Player)

        Portions Copyright (C) 1999-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: cdpmo.cpp,v 1.8 2003/09/16 17:34:59 kgk Exp $
____________________________________________________________________________*/

/* system headers */
#include <assert.h>
#include <string>
#include <vector>
/* project headers */

using namespace std;
#include "config.h"
#ifdef WIN32
#else
#include "cdaudio.h"
#endif

#include "cdpmo.h"
#include "lmc.h"
#include "eventdata.h"
#include "facontext.h"
#include "log.h"

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

extern    "C"
{
   PhysicalMediaOutput *Initialize(FAContext *context)
   {
      return new CDPMO(context);
   }
}

CDPMO::CDPMO(FAContext *context) :
       PhysicalMediaOutput(context)
{
   m_properlyInitialized = false;

   m_pBufferThread = NULL;
   m_track = -1;
   m_cdDesc = -1;
   sentData = false;
   trackDone = false;
}

CDPMO::~CDPMO()
{
   m_bExit = true;

   if (m_pBufferThread)
   {
      m_pBufferThread->Join();
      delete m_pBufferThread;
   }

   if (m_properlyInitialized)
       Reset(true);

   cd_finish(m_cdDesc);
}

void CDPMO::SetVolume( int32_t left, int32_t right)
{
    if (m_cdDesc != -1)
    {
        left = (int32_t)(((double)left / (double)100) * (double)255);
        right = (int32_t)(((double)right / (double)100) * (double)255);
        struct disc_volume vol;

        vol.vol_front.left = left;
        vol.vol_back.right = right;

        cd_set_volume(m_cdDesc, vol);
    }
}

void CDPMO::GetVolume(int32_t &left, int32_t &right)
{
    left = right = -1;
    if (m_cdDesc != -1)
    {
        struct disc_volume vol;
      
        cd_get_volume(m_cdDesc, &vol);
        left = (int32_t)(((double)vol.vol_front.left / (double)255) * 100);
        right = (int32_t)(((double)vol.vol_front.right / (double)255) * 100);
    }
} 

Error CDPMO::SetTo(const char *url)
{
   OutputInfo blah;

   if (IsError(Init(&blah))) 
       return kError_CDInitFailed;

   char *tracknumber = strrchr(url, '/');

   if (!tracknumber)
       tracknumber = (char *)url;
   else
       tracknumber++;

   m_track = atoi(tracknumber);

   if (m_track < 1 || m_track > MAX_TRACKS)
       return kError_InvalidTrack;

   if (!m_pBufferThread)
   {
      m_pBufferThread = Thread::CreateThread();
      assert(m_pBufferThread);
      m_pBufferThread->Create(CDPMO::StartWorkerThread, this);
   }

   cd_play_track(m_cdDesc, m_track, m_track);

   m_properlyInitialized = true;
   return kError_NoErr;
}

Error CDPMO::Init(OutputInfo *info)
{
   string device;

   if (IsError(m_pContext->prefs->GetPrefString(kCDDevicePathPref, &device)))
           return (Error)pmoError_DeviceOpenFailed;

   m_cdDesc = cd_init_device((char*)device.c_str());

   if (m_cdDesc < 0) {
       if (info)
           ReportError(_("Cannot open the CD-ROM device.  Please make sure that "
                       "the CD Device preference is set properly."));
       return (Error)pmoError_DeviceOpenFailed;
   }

   cddbid = 0;
   cdindexid = "";

   if (cd_stat(m_cdDesc, &dinfo, false) < 0) {
       if (info)
           ReportError(_("There is no disc in the CD-ROM drive."));

       return kError_NoDiscInDrive;
   }
   
   if (!dinfo.disc_present) {
       if (info)
           ReportError(_("There is no disc in the CD-ROM drive."));
       return kError_NoDiscInDrive;
   }

   cd_stat(m_cdDesc, &dinfo);

   uint32_t tracks = dinfo.disc_total_tracks;
   cddbid = cddb_direct_discid(dinfo);
   char *cdindex = new char[256];
   cdindex_direct_discid(dinfo, cdindex, 256);

   cdindexid = cdindex;

   CDInfoEvent *cie = new CDInfoEvent(tracks, cddbid, cdindex);

   m_pTarget->AcceptEvent(cie);

   delete [] cdindex;

   return kError_NoErr;
}

uint32_t CDPMO::GetCDDBDiscID(void)
{
   return cddbid;
}

char *CDPMO::GetcdindexDiscID(void)
{
    return (char *)cdindexid.c_str();
}

struct disc_info *CDPMO::GetDiscInfo(void)
{
    return &dinfo;
}

void CDPMO::Eject(void)
{
    if (m_cdDesc < 0)
        return;

    cd_eject(m_cdDesc);
}

Error CDPMO::Reset(bool user_stop)
{
   if (m_cdDesc < 0)
      return kError_NoErr;

   if (user_stop)
   {
       cd_stop(m_cdDesc);
   }
   else
   {
       cd_stop(m_cdDesc);
   }
   return kError_NoErr;
}

void CDPMO::Pause(void)
{
    if (m_cdDesc < 0)
        return;

    cd_pause(m_cdDesc);
}

void CDPMO::Resume(void)
{
    if (m_cdDesc < 0)
        return;

    cd_resume(m_cdDesc);
}

Error CDPMO::ChangePosition(int32_t newposition)
{
    if (m_cdDesc < 0 || m_track < 0)
        return kError_NoErr;

    cd_play_track_pos(m_cdDesc, m_track, m_track, newposition);

    return kError_NoErr;
}

void CDPMO::HandleTimeInfoEvent(PMOTimeInfoEvent *pEvent)
{
   if (m_cdDesc < 0 || m_track < 0)
      return;

   struct disc_info disc;
   struct disc_timeval val;

   if (cd_stat(m_cdDesc, &disc, false) < 0) {
       trackDone = true;
       return;
   }
 
   if (!disc.disc_present) {
       trackDone = true;
       return;
   }

   cd_stat(m_cdDesc, &disc);

   if (!sentData) {
       val = disc.disc_track[m_track - 1].track_length;
       uint32_t length = val.minutes * 60 + val.seconds;

       char *url = new char[30];
       sprintf(url, _("CD Track %d"), m_track);

       MediaInfoEvent *mie = new MediaInfoEvent(url, length*1000);

       MpegInfoEvent *mpie = new MpegInfoEvent(length, 1, 0, 1411200, 44100, 0,
                                               0, 1, 0, 0, 0, 1, 0);
       mie->AddChildEvent((Event *)mpie);
       m_pTarget->AcceptEvent(mie);
       sentData = true;
   }

   if (m_track < disc.disc_current_track || (disc.disc_mode != CDAUDIO_PLAYING
       && disc.disc_mode != CDAUDIO_PAUSED))
   {
       trackDone = true;
   }
    
   int iTotalTime = disc.disc_track_time.minutes * 60 + 
                    disc.disc_track_time.seconds; 

   MediaTimeInfoEvent *pmtpi = new MediaTimeInfoEvent( iTotalTime*1000, 
                                                       0 /*TODO*/ );
   m_pTarget->AcceptEvent(pmtpi);
}

void CDPMO::StartWorkerThread(void *pVoidBuffer)
{
   ((CDPMO*)pVoidBuffer)->WorkerThread();
}

void CDPMO::WorkerThread(void)
{
#ifdef __linux__
   struct sched_param sParam;

   sParam.sched_priority = sched_get_priority_max(SCHED_OTHER);
   pthread_setschedparam(pthread_self(), SCHED_OTHER, &sParam);
#endif

   for(; !m_bExit;)
   {
      // Loop until we get an Init event from the LMC
      if (!m_properlyInitialized)
      {
          WasteTime();
      }
      else {
          HandleTimeInfoEvent(NULL);
   
          if (trackDone)
          {
              m_pTarget->AcceptEvent(new Event(INFO_DoneOutputting));

              return;
          }
          WasteTime();
      }
   }
}

/* arch-tag: ce1ee969-f667-41de-99ec-44f5d2c14662
   (do not change this comment) */

Generated by  Doxygen 1.6.0   Back to index