예제 #1
0
void S_StopBackgroundTrack( void )
{
    bgTrack_t *next;

    if( source )
        qalSourceStop( source );

    if( alloced_buffers ) {
        qalSourceUnqueueBuffers( source, MUSIC_BUFFERS, buffers );
        qalDeleteBuffers( MUSIC_BUFFERS, buffers );
        alloced_buffers = queued_buffers = qfalse;
    }

    music_source_free();

    qalGetError();

    while( s_bgTrackHead )
    {
        next = s_bgTrackHead->anext;

        S_CloseMusicTrack( s_bgTrackHead );
        S_Free( s_bgTrackHead );

        s_bgTrackHead = next;
    }

    s_bgTrack = NULL;
    s_bgTrackHead = NULL;

    s_bgTrackBuffering = qfalse;

    s_bgTrackPaused = qfalse;
}
예제 #2
0
파일: snd_music.c 프로젝트: Picmip/qfusion
/*
* S_StartBackgroundTrack
*/
void S_StartBackgroundTrack( const char *intro, const char *loop, int mode ) {
	const char *ext;
	bgTrack_t *introTrack, *loopTrack;
	bgTrack_t *firstTrack = NULL;

	S_StopBackgroundTrack();

	if( !intro || !intro[0] ) {
		return;
	}

	s_bgTrackMuted = false;
	s_bgTrackPaused = false;

	ext = COM_FileExtension( intro );
	if( ext && !Q_stricmp( ext, ".m3u" ) ) {
		// mode bits:
		// 1 - shuffle
		// 2 - loop the selected track
		// 4 - stream (even if muted)

		firstTrack = S_ReadPlaylistFile( intro,
										 mode & 1 ? true : false, mode & 2 ? true : false );
		if( firstTrack ) {
			goto start_playback;
		}
	}

	// the intro track loops unless another loop track has been specified
	introTrack = S_AllocTrack( intro );
	introTrack->loop = true;
	introTrack->next = introTrack->prev = introTrack;
	introTrack->muteOnPause = introTrack->isUrl || mode & 4 ? true : false;

	if( loop && loop[0] && Q_stricmp( intro, loop ) ) {
		loopTrack = S_AllocTrack( loop );
		if( S_OpenMusicTrack( loopTrack, NULL ) ) {
			S_CloseMusicTrack( loopTrack );

			introTrack->next = introTrack->prev = loopTrack;
			introTrack->loop = false;

			loopTrack->loop = true;
			loopTrack->muteOnPause = loopTrack->isUrl || mode & 4 ? true : false;
			loopTrack->next = loopTrack->prev = loopTrack;
		}
	}

	firstTrack = introTrack;

start_playback:

	if( !firstTrack || firstTrack->ignore ) {
		S_StopBackgroundTrack();
		return;
	}

	S_OpenBackgroundTrackTask( firstTrack );
}
예제 #3
0
/*
* S_OpenMusicTrack
*/
static qboolean S_OpenMusicTrack( bgTrack_t *track )
{
    const char *filename = track->filename;

    if( track->ignore )
        return qfalse;

mark0:
    s_bgTrackBuffering = qfalse;

    if( !track->stream )
    {
        qboolean delay = qfalse;

        track->stream = S_OpenStream( filename, &delay );
        if( track->stream && delay )
        {
            // let the background track buffer for a while
            Com_Printf( "S_OpenMusicTrack: buffering %s...\n", track->filename );
            s_bgTrackBuffering = qtrue;
        }
    }
    else
    {
        if( !S_ResetStream( track->stream ) )
        {
            // if seeking failed for whatever reason (stream?), try reopening again
            S_CloseMusicTrack( track );
            goto mark0;
        }
    }

    if( !S_ValidMusicFile( track ) )
    {
        S_CloseMusicTrack( track );

        // mark as permanently invalid
        track->ignore = qtrue;
        Com_Printf( "Invalid music file %s\n", filename );
        return qfalse;
    }

    return qtrue;
}
예제 #4
0
/*
* S_OpenMusicTrack
*/
static bool S_OpenMusicTrack( bgTrack_t *track, bool *buffering )
{
	if( track->ignore )
		return false;

mark0:
	if( buffering )
		*buffering = false;

	if( !track->file )
	{
		bool opened, delay = false;

		memset( &track->info, 0, sizeof( track->info ) );

		// try ogg
		track->open = SNDOGG_OpenTrack;
		opened = track->open( track, &delay );

		// try wav
		if( !opened )
		{
			track->open = S_BackgroundTrack_OpenWav;
			opened = track->open( track, &delay );
		}

		if( opened && delay )
		{
			// let the background track buffer for a while
			// Com_Printf( "S_OpenMusicTrack: buffering %s...\n", track->filename );
			if( buffering )
				*buffering = true;
		}
	}
	else
	{
		int seek;

		if( track->seek )
			seek = track->seek( track, 0 );
		else
			seek = trap_FS_Seek( track->file, track->info.dataofs, FS_SEEK_SET );

		// if seeking failed for whatever reason (stream?), try reopening again
		if( seek )
		{
			S_CloseMusicTrack( track );
			goto mark0;
		}
	}

	return true;
}
예제 #5
0
static qboolean music_process( ALuint b )
{
    int l = 0;
    ALuint format;
    ALenum error;
    snd_stream_t *music_stream;

start:
    if( s_bgTrackBuffering )
        return qtrue;

    music_stream = s_bgTrack->stream;
    if( music_stream ) {
        l = S_ReadStream( music_stream, MUSIC_BUFFER_SIZE, decode_buffer );
    }
    else {
        l = 0;
    }

    if( !l )
    {
        bgTrack_t *cur;

        cur = s_bgTrack;
        if( !S_AdvanceBackgroundTrack( 1 ) )
        {
            if( !S_ValidMusicFile( s_bgTrack ) )
                return qfalse;
        }
        else
        {
            // we've advanced to the next track, close this one
            S_CloseMusicTrack( cur );
            goto start;
        }

        if( !S_ResetStream( music_stream ) )
        {
            // if failed, close the track?
            return qfalse;
        }

        goto start;
    }

    format = S_SoundFormat( music_stream->info.width, music_stream->info.channels );
    qalBufferData( b, format, decode_buffer, l, music_stream->info.rate );
    if( ( error = qalGetError() ) != AL_NO_ERROR )
        return qfalse;

    return qtrue;
}
예제 #6
0
/*
* S_PauseBackgroundTrack
*/
void S_PauseBackgroundTrack( void )
{
    if( !s_bgTrack ) {
        return;
    }

    // in case of a streaming URL, reset the stream
    if( s_bgTrack->isUrl ) {
        if( s_bgTrackPaused ) {
            S_OpenMusicTrack( s_bgTrack );
        }
        else {
            S_CloseMusicTrack( s_bgTrack );
        }
    }

    s_bgTrackPaused = !s_bgTrackPaused;
}
예제 #7
0
파일: snd_music.c 프로젝트: Picmip/qfusion
/*
* S_AdvanceBackgroundTrack
*/
static bool S_AdvanceBackgroundTrack( int n ) {
	bgTrack_t *track;

	if( n < 0 ) {
		track = S_PrevMusicTrack( s_bgTrack );
	} else {
		track = S_NextMusicTrack( s_bgTrack );
	}

	if( track && track != s_bgTrack ) {
		S_CloseBackgroundTrackTask();
		S_CloseMusicTrack( s_bgTrack );
		S_OpenBackgroundTrackTask( track );
		return true;
	}

	return false;
}
예제 #8
0
/*
* S_AdvanceBackgroundTrack
*/
static qboolean S_AdvanceBackgroundTrack( int n )
{
    bgTrack_t *track;

    if( n < 0 )
        track = S_PrevMusicTrack( s_bgTrack );
    else
        track = S_NextMusicTrack( s_bgTrack );

    if( track && track != s_bgTrack )
    {
        if( s_bgTrack->isUrl )
            S_CloseMusicTrack( s_bgTrack );
        s_bgTrack = track;
        return qtrue;
    }

    return qfalse;
}
예제 #9
0
파일: snd_music.c 프로젝트: Picmip/qfusion
/*
* S_StopBackgroundTrack
*/
void S_StopBackgroundTrack( void ) {
	bgTrack_t *next;

	S_CloseBackgroundTrackTask();

	while( s_bgTrackHead ) {
		next = s_bgTrackHead->anext;

		S_CloseMusicTrack( s_bgTrackHead );
		S_Free( s_bgTrackHead );

		s_bgTrackHead = next;
	}

	s_bgTrack = NULL;
	s_bgTrackHead = NULL;

	s_bgTrackMuted = false;
	s_bgTrackPaused = false;
}
예제 #10
0
void S_StartBackgroundTrack( const char *intro, const char *loop )
{
    int count;
    const char *ext;
    bgTrack_t *t, f;
    bgTrack_t *introTrack, *loopTrack;
    ALenum error;
    int mode = 0;

    // Stop any existing music that might be playing
    S_StopBackgroundTrack();

    if( !intro || !intro[0] )
        return;

    s_bgTrackPaused = qfalse;

    ext = COM_FileExtension( intro );
    if( ext && !Q_stricmp( ext, ".m3u" ) )
    {
        // mode bits:
        // 1 - shuffle
        // 2 - loop the selected track
        if( loop && loop[0] )
            mode = atoi( loop );

        if( S_ReadPlaylistFile( intro, mode & 1 ? qtrue : qfalse ) )
            goto start_playback;
    }

    // the intro track loops unless another loop track has been specified
    introTrack = S_AllocTrack( intro );
    introTrack->next = introTrack->prev = introTrack;

    if( loop && loop[0] && Q_stricmp( intro, loop ) )
    {
        loopTrack = S_AllocTrack( loop );
        if( S_OpenMusicTrack( loopTrack ) )
        {
            S_CloseMusicTrack( loopTrack );
            loopTrack->next = introTrack->next = introTrack->prev = loopTrack;
            loopTrack->prev = introTrack;
        }
    }

    s_bgTrack = introTrack;

start_playback:
    // this effectively precaches the first 15 scheduled tracks in the playlist
    for( count = 0, t = s_bgTrack; count < 15 && t && t != s_bgTrack; count++ )
    {
        if( !t->isUrl )
        {
            S_OpenMusicTrack( t );

            if( t->next == t || t->next == s_bgTrack )
                break; // break on an endless loop or full cycle
            if( !t->ignore && ( mode & 2 ) )
            {
                // no point in precaching the whole playlist when we're only going
                // to loop one single track
                break;
            }
        }
        t = t->next;
    }

    // start playback with the first valid track
    if( count > 1 )
    {
        memset( &f, 0, sizeof( f ) );
        f.next = s_bgTrack;

        s_bgTrack = S_NextMusicTrack( &f );
    }
    else
    {
        S_OpenMusicTrack( s_bgTrack );
    }

    if( !s_bgTrack || s_bgTrack->ignore )
    {
        S_StopBackgroundTrack();
        return;
    }

    if( mode & 2 )
    {
        // loop the same track over and over
        s_bgTrack->next = s_bgTrack->prev = s_bgTrack;
    }

    music_source_get();
    if( !src )
    {
        Com_Printf( "Error couldn't get source for music\n" );
        S_StopBackgroundTrack();
        return;
    }

    alloced_buffers = qfalse;
    queued_buffers = qfalse;

    qalGenBuffers( MUSIC_BUFFERS, buffers );
    if( ( error = qalGetError() ) != AL_NO_ERROR )
    {
        Com_Printf( "Error couldn't generate music buffers (%s)\n", S_ErrorMessage( error ) );
        S_StopBackgroundTrack();
        return;
    }

    alloced_buffers = qtrue;
}
예제 #11
0
void S_UpdateMusic( void )
{
    int i, processed;
    ALint state;
    ALenum error;
    ALuint b;
    int num_processed_buffers;
    ALuint processed_buffers[MUSIC_BUFFERS];

    if( !s_bgTrack )
        return;
    if( !s_musicvolume->value && !s_bgTrack->isUrl )
        return;
    if( s_bgTrackPaused || s_bgTrackLocked )
        return;

    if( s_bgTrackBuffering )
    {
        if( S_EoStream( s_bgTrack->stream ) ) {
            // we should now advance to the next track
            S_CloseMusicTrack( s_bgTrack );
        }
        else {
            if( S_FTellSteam( s_bgTrack->stream ) < BACKGROUND_TRACK_BUFFERING_SIZE )
                return;

            // in case we delayed openening to let the stream be cached for a while,
            // start actually reading from it now
            if( !S_ContOpenStream( s_bgTrack->stream ) ) {
                // let music_process do the dirty job of advancing to the next track
                S_CloseMusicTrack( s_bgTrack );
                s_bgTrack->ignore = qtrue;
            }
        }
        s_bgTrackBuffering = qfalse;
    }

    if( !queued_buffers )
    {
        // if we haven't queued any buffers yet, do it now
        num_processed_buffers = MUSIC_BUFFERS;
        memcpy( processed_buffers, buffers, sizeof( buffers ) );
    }
    else
    {
        num_processed_buffers = 0;

        processed = 0;
        qalGetSourcei( source, AL_BUFFERS_PROCESSED, &processed );
        while( processed-- )
        {
            qalSourceUnqueueBuffers( source, 1, &b );
            processed_buffers[num_processed_buffers++] = b;
        }
    }

    for( i = 0; i < num_processed_buffers; i++ )
    {
        b = processed_buffers[i];
        if( !music_process( b ) )
        {
            Com_Printf( "Error processing music data\n" );
            S_StopBackgroundTrack();
            return;
        }

        qalSourceQueueBuffers( source, 1, &b );
        if( ( error = qalGetError() ) != AL_NO_ERROR )
        {
            Com_Printf( "Couldn't queue music data (%s)\n", S_ErrorMessage( error ) );
            S_StopBackgroundTrack();
            return;
        }
    }

    // If it's not still playing, give it a kick
    qalGetSourcei( source, AL_SOURCE_STATE, &state );
    if( !queued_buffers || state != AL_PLAYING )
    {
        queued_buffers = qtrue;
        qalSourcePlay( source );
    }

    if( s_musicvolume->modified )
        qalSourcef( source, AL_GAIN, s_musicvolume->value );
}