void SjPlayer::GotoAbsPos(long queuePos, bool fadeToPos)
{
	// This function may only be called from the main thread.
	wxASSERT( wxThread::IsMain() );

	if( !m_isInitialized ) {
		return;
	}

	static bool inHere = false;
	if( !inHere )
	{
		inHere = true;

		m_stopAfterThisTrack = false;

		// check offset
		if( queuePos < 0
		 || queuePos >= m_queue.GetCount() )
		{
			inHere = false; // don't forget this!
			return;
		}

		// goto absolute track
		m_queue.SetCurrPos(queuePos);

		if( IsPaused() )
		{
			// switch from pause to stop
			Stop();
		}
		else if( IsPlaying() )
		{
			// playing, realize the new position in the implementation
			DoGotoAbsPos(queuePos, fadeToPos);
		}

		SendSignalToMainThread(IDMODMSG_TRACK_ON_AIR_CHANGED);

		inHere = false;
	}
}
void SjPlayer::DoReceiveSignal(int signal, uintptr_t extraLong)
{
	if( !m_impl->InitXine() ) {
		return; // error
	}

	if( signal == THREAD_PREPARE_NEXT )
	{
		// find out the next url to play
		wxString	newUrl;
		//long		newQueueId = 0;
		long		newQueuePos = m_queue.GetCurrPos();

		// try to get next url from queue
		newQueuePos = m_queue.GetNextPos(SJ_PREVNEXT_REGARD_REPEAT);
		if( newQueuePos == -1 )
		{
			// try to enqueue auto-play url
			g_mainFrame->m_autoCtrl.DoAutoPlayIfEnabled(false /*ignoreTimeouts*/);
			newQueuePos = m_queue.GetNextPos(SJ_PREVNEXT_REGARD_REPEAT);

			if( newQueuePos == -1 )
			{
				// no chance, there is nothing more to play ...
				if( signal == THREAD_OUT_OF_DATA )
				{
					Stop();
					SendSignalToMainThread(IDMODMSG_PLAYER_STOPPED_BY_EOQ);
				}
				return;
			}
		}
		newUrl = m_queue.GetUrlByPos(newQueuePos);
		//newQueueId = m_queue.GetIdByPos(newQueuePos);

		// has the URL just failed? try again in the next message look
		wxLogDebug(wxT(" ... SjPlayer::ReceiveSignal(): new URL is \"%s\""), newUrl.c_str());

		if( m_failedUrls.Index( newUrl ) != wxNOT_FOUND )
		{
			wxLogDebug(wxT(" ... SjPlayer::ReceiveSignal(): the URL has failed before, starting over."));
			m_queue.SetCurrPos(newQueuePos);
			SendSignalToMainThread(signal); // start over
			return;
		}

		// try to create the next stream
        if( m_impl->m_currStream ) {
			delete m_impl->m_currStream;
			m_impl->m_currStream = NULL;
		}
		m_impl->m_currStream = new SjXineStream(m_impl, newUrl);
		if( !m_impl->m_currStream->XinePlay() ) {
			wxLogDebug(wxT(" ... SjPlayer::ReceiveSignal(): cannot create the new stream."));
			delete m_impl->m_currStream;
			m_impl->m_currStream = NULL;
		}

		// realize the new position in the UI
		m_queue.SetCurrPos(newQueuePos);
		SendSignalToMainThread(IDMODMSG_TRACK_ON_AIR_CHANGED);
	}
}
void SjPlayer::DoReceiveSignal(int signal, uintptr_t extraLong)
{
	wxLogDebug("SjPlayer::DoReceiveSignal() called ... ");

	if( !m_impl->InitXine() ) {
		wxLogDebug(wxT(" ... error: xine ist not ready."));
		return; // error
	}

	if( signal == THREAD_PREPARE_NEXT || signal == THREAD_OUT_OF_DATA )
	{
		// find out the next url to play
		wxString	newUrl;

		// try to get next url from queue
		long newQueuePos = m_queue.GetNextPos(SJ_PREVNEXT_REGARD_REPEAT);
		if( newQueuePos == -1 )
		{
			// try to enqueue auto-play url
			g_mainFrame->m_autoCtrl.DoAutoPlayIfEnabled(false /*ignoreTimeouts*/);
			newQueuePos = m_queue.GetNextPos(SJ_PREVNEXT_REGARD_REPEAT);

			if( newQueuePos == -1 )
			{
				// no chance, there is nothing more to play ...
				if( signal == THREAD_PREPARE_NEXT )
				{
					g_mainFrame->m_player.SendSignalToMainThread(THREAD_OUT_OF_DATA); // send a modified signal, no direct call as Receivesignal() will handle some cases exclusively
				}
				else if( signal == THREAD_OUT_OF_DATA )
				{
					wxLogDebug(wxT(" ... receiving THREAD_OUT_OF_DATA, stopping and sending IDMODMSG_PLAYER_STOPPED_BY_EOQ"));
					Stop();
					SendSignalToMainThread(IDMODMSG_PLAYER_STOPPED_BY_EOQ);
				}
				return;
			}
		}
		newUrl = m_queue.GetUrlByPos(newQueuePos);

		// has the URL just failed? try again in the next message look
		wxLogDebug(wxT(" ... new URL is \"%s\""), newUrl.c_str());

		if( m_failedUrls.Index( newUrl ) != wxNOT_FOUND )
		{
			wxLogDebug(wxT(" ... the URL has failed before, starting over."));
			m_queue.SetCurrPos(newQueuePos);
			SendSignalToMainThread(signal); // start over
			return;
		}

		// try to create the next stream
        if( m_impl->m_currStream ) {
			m_impl->m_currStream->PlaybackDone();
			delete m_impl->m_currStream;
			m_impl->m_currStream = NULL;
		}
		m_impl->m_currStream = new SjXineStream(m_impl, newUrl);
		if( !m_impl->m_currStream->XinePlay() ) {
			wxLogDebug(wxT(" ... cannot create the new stream."));
			delete m_impl->m_currStream;
			m_impl->m_currStream = NULL;
		}

		// realize the new position in the UI
		m_queue.SetCurrPos(newQueuePos);
		SendSignalToMainThread(IDMODMSG_TRACK_ON_AIR_CHANGED);
	}
}