void ShoutCastIODevice::socketError(QAbstractSocket::SocketError error) { switch (error) { case QAbstractSocket::ConnectionRefusedError: LOG(VB_NETWORK, LOG_ERR, "ShoutCastIODevice: Error Connection Refused"); switchToState(CANT_CONNECT); break; case QAbstractSocket::RemoteHostClosedError: LOG(VB_NETWORK, LOG_ERR, "ShoutCastIODevice: Error Remote Host Closed The Connection"); switchToState(CANT_CONNECT); break; case QAbstractSocket::HostNotFoundError: LOG(VB_NETWORK, LOG_ERR, "ShoutCastIODevice: Error Host Not Found"); switchToState(CANT_RESOLVE); break; case QAbstractSocket::SocketTimeoutError: LOG(VB_NETWORK, LOG_ERR, "ShoutCastIODevice: Error Socket Timeout"); switchToState(STOPPED); break; default: LOG(VB_NETWORK, LOG_ERR, QString("ShoutCastIODevice: Got socket error '%1'") .arg(errorString())); switchToState(STOPPED); break; } }
void ShoutCastIODevice::socketConnected(void) { LOG(VB_NETWORK, LOG_INFO, "ShoutCastIODevice: Connected"); switchToState(CONNECTED); ShoutCastRequest request(m_url); qint64 written = m_socket->write(request.data(), request.size()); LOG(VB_NETWORK, LOG_INFO, QString("ShoutCastIODevice: Sending Request, %1 of %2 bytes") .arg(written).arg(request.size())); if (written != request.size()) { LOG(VB_NETWORK, LOG_INFO, "ShoutCastIODevice: buffering write"); m_scratchpad = QByteArray(request.data() + written, request.size() - written); m_scratchpad_pos = 0; connect(m_socket, SIGNAL (bytesWritten(qint64)), SLOT(socketBytesWritten(qint64))); switchToState(WRITING_HEADER); } else switchToState(READING_HEADER); m_started = false; m_bytesDownloaded = 0; m_bytesTillNextMeta = 0; m_response_gotten = false; }
void ShoutCastIODevice::socketReadyRead(void) { // only read enough data to fill our buffer int available = DecoderIOFactory::DefaultBufferSize - m_buffer->readBufAvail(); QByteArray data = m_socket->read(available); m_bytesDownloaded += data.size(); m_buffer->write(data); // send buffer status event emit bufferStatus(m_buffer->readBufAvail(), DecoderIOFactory::DefaultBufferSize); if (!m_started && m_bytesDownloaded > DecoderIOFactory::DefaultPrebufferSize) { m_socket->setReadBufferSize(DecoderIOFactory::DefaultPrebufferSize); m_started = true; } // if we are waiting for the HEADER and we have enough data process that if (m_state == READING_HEADER) { if (parseHeader()) { if (m_response->getStatus() == 200) { switchToState(PLAYING); m_response_gotten = true; m_bytesTillNextMeta = m_response->getMetaint(); switchToState(STREAMING); } else if (m_response->getStatus() == 302 || m_response->getStatus() == 301) { if (++m_redirects > MAX_REDIRECTS) { LOG(VB_NETWORK, LOG_ERR, QString("Too many redirects")); switchToState(STOPPED); } else { LOG(VB_NETWORK, LOG_INFO, QString("Redirect to %1").arg(m_response->getLocation())); m_socket->close(); QUrl redirectURL(m_response->getLocation()); connectToUrl(redirectURL); return; } } else { LOG(VB_NETWORK, LOG_ERR, QString("Unknown response status %1") .arg(m_response->getStatus())); switchToState(STOPPED); } } } }
bool ShoutCastIODevice::parseMeta(void) { QByteArray data; m_buffer->read(data, 1); unsigned char ch = data[0]; qint64 meta_size = 16 * ch; if (meta_size == 0) return true; // sanity check if (meta_size > MAX_ALLOWED_META_SIZE) { LOG(VB_PLAYBACK, LOG_ERR, QString("ShoutCastIODevice: Error in stream, got a meta size of %1") .arg(meta_size)); switchToState(STOPPED); return false; } LOG(VB_NETWORK, LOG_INFO, QString("ShoutCastIODevice: Reading %1 bytes of meta").arg(meta_size)); // read metadata from our buffer data.clear(); m_buffer->read(data, meta_size); // sanity check, check we have enough data if (meta_size > data.size()) { LOG(VB_PLAYBACK, LOG_ERR, QString("ShoutCastIODevice: Not enough data, we have %1, but the " "metadata size is %1") .arg(data.size()).arg(meta_size)); switchToState(STOPPED); return false; } QString metadataString = QString::fromUtf8(data.constData()); // avoid sending signals if the data hasn't changed if (m_last_metadata == metadataString) return true; m_last_metadata = metadataString; emit meta(metadataString); return true; }
qint64 ShoutCastIODevice::readData(char *data, qint64 maxlen) { // the decoder wants more data from the stream // but first we must filter out any headers and metadata if (m_buffer->readBufAvail() == 0) { LOG(VB_PLAYBACK, LOG_ERR, "ShoutCastIODevice: No data in buffer!!"); switchToState(STOPPED); return -1; } if (m_state == STREAMING_META && parseMeta()) switchToState(STREAMING); if (m_state == STREAMING) { if (m_bytesTillNextMeta > 0) { // take maxlen or what ever is left till the next metadata if (maxlen > m_bytesTillNextMeta) maxlen = m_bytesTillNextMeta; maxlen = m_buffer->read(data, maxlen); m_bytesTillNextMeta -= maxlen; if (m_bytesTillNextMeta == 0) switchToState(STREAMING_META); } else maxlen = m_buffer->read(data, maxlen); } if (m_state != STOPPED) LOG(VB_NETWORK, LOG_INFO, QString("ShoutCastIODevice: %1 kb in buffer, btnm=%2/%3 " "state=%4, len=%5") .arg(m_buffer->readBufAvail() / 1024, 4) .arg(m_bytesTillNextMeta, 4) .arg(m_response->getMetaint()) .arg(stateString (m_state)) .arg(maxlen)); else LOG(VB_NETWORK, LOG_INFO, QString("ShoutCastIODevice: stopped")); return maxlen; }
void StateManager::returnToTitle() { if (!dynamic_cast<FadeTransition*>(_currentState)) { switchToState(new FadeTransition([]() { return new TitleScreen; })); } }
void ShoutCastIODevice::connectToUrl(const QUrl &url) { m_url = url; switchToState (RESOLVING); setOpenMode(ReadWrite); open(ReadWrite); return m_socket->connectToHost(m_url.host(), m_url.port() == -1 ? 80 : m_url.port()); }
bool HibernationManager::switchToLevel ( int level ) { HibernatorBase::SLEEP_STATE state = m_hibernator->intToSleepState( level ); if ( state == HibernatorBase::NONE ) { dprintf( D_ALWAYS, "Can't switch to invalid level '%d'\n", level ); return false; } return switchToState( state ); }
bool HibernationManager::switchToState ( const char *name ) { HibernatorBase::SLEEP_STATE state = m_hibernator->stringToSleepState( name ); if ( state == HibernatorBase::NONE ) { dprintf( D_ALWAYS, "Can't switch to invalid state '%s'\n", name ); return false; } return switchToState( state ); }
void GStreamerPipeline::onBuffering( const QGst::BufferingMessagePtr &msg ) { int percent = msg->percent(); QGst::ObjectPtr source = msg->source(); int minPercent = 100; bool isFromRightSource = false; for( StreamInfo &info : mStreams ) { if( info.queue == source ) { isFromRightSource = true; if( percent <= 5 ) { info.isBuffering = true; switchToState( PS_Buffering ); } if( percent == 100 ) { info.isBuffering = false; } info.percent = percent; } if( info.isBuffering ) { minPercent = std::min( minPercent, info.percent ); } } if( !isFromRightSource ) return; qDebug() << "Buffering... " << minPercent << "Source: " << source->name(); buffering( minPercent ); if( minPercent == 100 ) { finnishedBuffering(); if( mPlayAfterBuffering ) { switchToState( PS_Playing ); } else { switchToState( PS_Paused ); } } }
void ShoutCastIODevice::socketBytesWritten(qint64) { qint64 written = m_socket->write(m_scratchpad.data() + m_scratchpad_pos, m_scratchpad.size() - m_scratchpad_pos); LOG(VB_NETWORK, LOG_INFO, QString("ShoutCastIO: %1 bytes written").arg(written)); m_scratchpad_pos += written; if (m_scratchpad_pos == m_scratchpad.size()) { m_scratchpad.truncate(0); disconnect (m_socket, SIGNAL(bytesWritten(qint64)), this, 0); switchToState(READING_HEADER); } }
ShoutCastIODevice::ShoutCastIODevice(void) : m_redirects (0), m_scratchpad_pos (0), m_state (NOT_CONNECTED) { m_socket = new QTcpSocket; m_response = new ShoutCastResponse; connect(m_socket, SIGNAL(hostFound()), SLOT(socketHostFound())); connect(m_socket, SIGNAL(connected()), SLOT(socketConnected())); connect(m_socket, SIGNAL(disconnected()), SLOT(socketConnectionClosed())); connect(m_socket, SIGNAL(readyRead()), SLOT(socketReadyRead())); connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError(QAbstractSocket::SocketError))); switchToState(NOT_CONNECTED); setOpenMode(ReadWrite); }
bool HibernationManager::switchToTargetState ( void ) { return switchToState( m_target_state ); }
void GStreamerPipeline::play() { switchToState( PS_Playing ); }
void GStreamerPipeline::pause() { switchToState( PS_Paused ); }
void ShoutCastIODevice::socketConnectionClosed(void) { LOG(VB_NETWORK, LOG_INFO, "ShoutCastIODevice: Connection Closed"); switchToState(STOPPED); }
void GStreamerPipeline::onEos() { switchToState( PS_Finnished ); }
void ShoutCastIODevice::socketHostFound(void) { LOG(VB_NETWORK, LOG_INFO, "ShoutCastIODevice: Host Found"); switchToState(CONNECTING); }