helix-engine.cpp

来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 898 行 · 第 1/2 页

CPP
898
字号
   {      m_state = Engine::Idle;      emit stateChanged( m_state );      emit trackEnded();   }}voidHelixEngine::pause(){   if (!m_inited)      return;   // TODO: PAUSE in XFADE   debug() << "In pause\n";   if( m_state == Engine::Playing )   {      PlayerControl::pause(m_current);      m_state = Engine::Paused;      emit stateChanged( Engine::Paused );   }}voidHelixEngine::unpause(){   if (!m_inited)      return;   // TODO: PAUSE in XFADE   debug() << "In unpause\n";   if ( m_state == Engine::Paused )   {      PlayerControl::resume(m_current);      m_state = Engine::Playing;      emit stateChanged( Engine::Playing );   }}Engine::StateHelixEngine::state() const{   //debug() << "In state, state is " << m_state << endl;   if (!m_inited || m_url.isEmpty())      return (Engine::Empty);   return m_state;}uintHelixEngine::position() const{   if (!m_inited)      return 0;   return PlayerControl::where(m_current);}uintHelixEngine::length() const{   if (!m_inited)      return 0;   return PlayerControl::duration(m_current);}voidHelixEngine::seek( uint ms ){   if (!m_inited)      return;   debug() << "In seek\n";   resetScope(0);   resetScope(1);   PlayerControl::seek(ms, m_current);}voidHelixEngine::setVolumeSW( uint vol ){   if (!m_inited)      return;   debug() << "In setVolumeSW\n";   PlayerControl::setVolume(vol); // set the volume in all players!}boolHelixEngine::canDecode( const KURL &url ) const{   if (!m_inited)      return false;   debug() << "In canDecode " << url.prettyURL() << endl;   if (url.protocol() == "http" || url.protocol() == "rtsp")      return true;   const QString path = url.path();   const QString ext  = path.mid( path.findRev( '.' ) + 1 ).lower();   if (ext != "txt")      for (int i=0; i<(int)m_mimes.size(); i++)      {         if (m_mimes[i].type.grep("audio").count() ||             m_mimes[i].type.grep("video").count() ||             m_mimes[i].type.grep("application").count())            if (m_mimes[i].ext.grep(ext).count())            {               return true;            }      }   return false;}voidHelixEngine::timerEvent( QTimerEvent * ){   PlayerControl::dispatch(); // dispatch the players   if ( m_xfadeLength <= 0 && m_state == Engine::Playing && PlayerControl::done(m_current) )      play_finished(m_current);   else if ( m_xfadeLength > 0 || AmarokConfig::fadeout() )   {      if ( m_state == Engine::Playing && isPlaying(m_current?0:1) && PlayerControl::done(m_current?0:1) )         hscope[m_current?0:1].m_lasttime = 0;      // fade on stop finished      if ( m_pfade[m_current].m_stopfade && m_pfade[m_current].m_fadeactive &&          (PlayerControl::where(m_current) > m_pfade[m_current].m_startfadetime + (unsigned)AmarokConfig::fadeoutLength() ||           PlayerControl::done(m_current)) )      {         debug() << "Stop fade end\n";         stop();      }      // crossfade finished      if ( m_pfade[m_current?0:1].m_fadeactive &&           PlayerControl::where(m_current?0:1) > m_pfade[m_current?0:1].m_startfadetime + (unsigned)m_xfadeLength)         play_finished(m_current?0:1);   }   // prune the scope(s)   prune();   struct timeval tm;   struct timezone tz;   memset(&tz, 0, sizeof(struct timezone));   gettimeofday(&tm, &tz);   m_scopedelta = (tm.tv_sec - m_scopetm.tv_sec) * 1000 + (tm.tv_usec - m_scopetm.tv_usec) / 1000; // ms   m_scopetm.tv_sec = tm.tv_sec;   m_scopetm.tv_usec = tm.tv_usec;   hscope[m_current].m_lasttime += m_scopedelta;   HelixSimplePlayer::metaData *md = getMetaData(m_current);   if (m_isStream &&       (strcmp(m_md.title, md->title) || strcmp(m_md.artist, md->artist)))   {      memcpy(&m_md, md, sizeof(m_md));      debug() << "{Title}: " << md->title << " {Artist}: " << md->artist << " {Bitrate}: " << md->bitrate << endl;      /* Real Radio One (and Rhapsody?) streams have their own format, where title is:       * clipinfo:title=<title>|artist name=<artist>|Album name=<album>|Artist:Next artist=<next artist>| \       * ordinal=<some number>|duration=<in secs>|Track:Rhapsody Track Id=<some number>       *       * for all other streams helix sends the title of the song in the artist string.       * this prevents context lookup, so we split it here (the artist and title are separated by a '-'       * we'll put the 'title' in album instead...       */      Engine::SimpleMetaBundle bndl;      bndl.album = QString::fromUtf8( m_md.title );      if ( bndl.album.startsWith( QString("clipinfo:") ) )      {         bndl.album = bndl.album.remove(0, 9);         QStringList sl = QStringList::split('|', bndl.album);         for ( QStringList::Iterator it = sl.begin(); it != sl.end(); ++it )         {            if ((*it).startsWith("title="))                bndl.title = (*it).section('=', 1, 1);            if ((*it).startsWith("artist name="))                bndl.artist = (*it).section('=', 1, 1);            if ((*it).startsWith("Album name="))                bndl.album = (*it).section('=', 1, 1);            if ((*it).startsWith("duration="))                bndl.length = (*it).section('=', 1, 1);         }         //debug() << "Title: " << bndl.title << endl;         //debug() << "Artist: " << bndl.artist << endl;         //debug() << "Album: " << bndl.album << endl;         //debug() << "length: " << bndl.length << endl;      }      else      {         char c,*tmp = strchr(m_md.artist, '-');         if (tmp)         {            tmp--;            c = *tmp;            *tmp = '\0';            bndl.artist = QString::fromUtf8( m_md.artist );            *tmp = c;            tmp+=3;            bndl.title = QString::fromUtf8( tmp );            bndl.album = QString::fromUtf8( m_md.title );         }         else // just copy them as is...         {            bndl.title = QString::fromUtf8( m_md.title );            bndl.artist = QString::fromUtf8( m_md.artist );         }      }      bndl.bitrate = QString::number( m_md.bitrate / 1000 );      emit EngineBase::metaData( bndl );   }}int HelixEngine::prune(){   int err = 0;   err |= prune(0);   err |= prune(1);   return err;}int HelixEngine::prune(int playerIndex){   //   // this bit is to help us keep more accurate time than helix provides   /////////////////////////////////////////////////////////////////////   unsigned long hpos = PlayerControl::where(playerIndex);   if (hpos != hscope[playerIndex].m_lastpos       && hpos - hscope[playerIndex].m_lastpos < hscope[playerIndex].m_lasttime - hscope[playerIndex].m_lastpos)      hscope[playerIndex].m_lasttime = hpos;   if (hpos > hscope[playerIndex].m_lasttime)   {      hscope[playerIndex].m_w = hpos;      hscope[playerIndex].m_lasttime = hpos;   }   else      hscope[playerIndex].m_w = hscope[playerIndex].m_lasttime;   hscope[playerIndex].m_lastpos = hpos;   if ( getScopeCount(playerIndex) > SCOPE_MAX_BEHIND ) // protect against naughty streams   {      resetScope(playerIndex);      return 0;   }   if (!hscope[playerIndex].m_w || !hscope[playerIndex].m_item)      return 0;   // prune, unless the player is still starting   while (hpos && hscope[playerIndex].m_item && hscope[playerIndex].m_w > hscope[playerIndex].m_item->etime)   {      //debug() << "pruning " << hpos << "," << hscope[playerIndex].m_w << "," << hscope[playerIndex].m_lasttime      //        << "," << hscope[playerIndex].m_item->time << ":" << hscope[playerIndex].m_item->etime << endl;      if (hscope[playerIndex].m_item && hscope[playerIndex].m_item->allocd)         delete hscope[playerIndex].m_item;      hscope[playerIndex].m_item = getScopeBuf(playerIndex);   }   if (!hscope[playerIndex].m_item)      return 0;   if (hscope[playerIndex].m_w < hscope[playerIndex].m_item->time) // wait for the player to catchup   {      //debug() << "waiting for player to catchup " << hpos << "," << hscope[playerIndex].m_w << "," << hscope[playerIndex].m_lasttime      //        << "," << hscope[playerIndex].m_item->time << ":" << hscope[playerIndex].m_item->etime << endl;      return 0;   }   return 1;}const Engine::Scope &HelixEngine::scope(){   if (isPlaying(0) && isPlaying(1)) // crossfading   {      if (m_scopeplayerlast)         scope(m_current);      else         scope(m_current?0:1);      m_scopeplayerlast = !m_scopeplayerlast;   }   else      scope(m_current);   return m_scope;}int HelixEngine::scope(int playerIndex){   int i;   unsigned long t;   if (!m_inited)      return 0;   if (!hscope[playerIndex].m_item && !peekScopeTime(t, playerIndex))      hscope[playerIndex].m_item = getScopeBuf(playerIndex);   if (!prune(playerIndex))      return 0;   if (hscope[playerIndex].m_item->nchan > 2)      return 0;   int j,k=0;   short int *pint;   unsigned char b[4];   // calculate the starting offset into the buffer   int off =  (hscope[playerIndex].m_item->spb * (hscope[playerIndex].m_w - hscope[playerIndex].m_item->time) /               (hscope[playerIndex].m_item->etime - hscope[playerIndex].m_item->time)) *              hscope[playerIndex].m_item->nchan * hscope[playerIndex].m_item->bps;   k = off;   while (hscope[playerIndex].m_item && hscope[playerIndex].m_scopeindex < SCOPESIZE)   {      while (k < (int) hscope[playerIndex].m_item->len)      {         for (j=0; j<hscope[playerIndex].m_item->nchan; j++)         {            switch (hscope[playerIndex].m_item->bps)            {               case 1:                  b[1] = 0;                  b[0] = hscope[playerIndex].m_item->buf[k];                  break;               case 2:                  b[1] = hscope[playerIndex].m_item->buf[k+1];                  b[0] = hscope[playerIndex].m_item->buf[k];                  break;            }            pint = (short *) &b[0];            if (hscope[playerIndex].m_item->nchan == 1) // duplicate mono samples            {               hscope[playerIndex].m_currentScope[hscope[playerIndex].m_scopeindex] = *pint;               hscope[playerIndex].m_scopeindex++;               hscope[playerIndex].m_currentScope[hscope[playerIndex].m_scopeindex] = *pint;               hscope[playerIndex].m_scopeindex++;            }            else            {               hscope[playerIndex].m_currentScope[hscope[playerIndex].m_scopeindex] = *pint;               hscope[playerIndex].m_scopeindex++;            }            k += hscope[playerIndex].m_item->bps;         }         if (hscope[playerIndex].m_scopeindex >= SCOPESIZE)         {            hscope[playerIndex].m_scopeindex = SCOPESIZE;            break;         }      }      // as long as we know there's another buffer...otherwise we need to wait for another      if (hscope[playerIndex].m_scopeindex < SCOPESIZE)      {         if (hscope[playerIndex].m_item && hscope[playerIndex].m_item->allocd)            delete hscope[playerIndex].m_item;         hscope[playerIndex].m_item = getScopeBuf(playerIndex);         k = 0;         if (!hscope[playerIndex].m_item)            return 0; // wait until there are some more buffers available      }      else      {         if (k >= (int) hscope[playerIndex].m_item->len)         {            if (hscope[playerIndex].m_item && hscope[playerIndex].m_item->allocd)               delete hscope[playerIndex].m_item;            hscope[playerIndex].m_item = getScopeBuf(playerIndex);         }         break; // done with the scope buffer, so hand it off      }   }   // ok, we must have a full buffer here, give it to the scope   for (i=0; i<SCOPESIZE; i++)      m_scope[i] = hscope[playerIndex].m_currentScope[i];   hscope[playerIndex].m_scopeindex = 0;   return 1;}voidHelixEngine::resetScope(int playerIndex){   if (playerIndex >=0 && playerIndex < numPlayers())   {      // make sure the scope is clear of old buffers      clearScopeQ(playerIndex);      hscope[playerIndex].m_scopeindex = 0;      if (hscope[playerIndex].m_item && hscope[playerIndex].m_item->allocd)         delete hscope[playerIndex].m_item;      hscope[playerIndex].m_w = 0;      hscope[playerIndex].m_item = 0;   }}voidHelixEngine::setEqualizerEnabled( bool enabled ) //SLOT{   enableEQ(enabled);}// ok, this is lifted from gst... but why mess with what works?voidHelixEngine::setEqualizerParameters( int preamp, const QValueList<int>& bandGains ) //SLOT{   m_preamp = ( preamp + 100 ) / 2;   m_equalizerGains.resize( bandGains.count() );   for ( uint i = 0; i < bandGains.count(); i++ )      m_equalizerGains[i] = ( *bandGains.at( i ) + 100 ) / 2;   updateEQgains();}namespace Debug{    #undef helix_indent    QCString helix_indent;}#include "helix-engine.moc"

⌨️ 快捷键说明

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