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 + -
显示快捷键?