示例#1
0
文件: sndqueue.c 项目: estock/spot
/* Destroy a sound session */
void snd_destroy (snd_SESSION * session)
{
	int ret = 0;
	oggBUFF *b;

	/* This will stop any playing sound too */
	if (session->actx)
		ret = audio_context_free (session->actx);

	/* Free the FIFO */
	if (session->fifo) {
		pthread_mutex_lock(&session->fifo->lock); /*rKA*/

		/* free oggBuffs */
		while (session->fifo->start) {
			b = session->fifo->start;
			session->fifo->start = session->fifo->start->next;
			DSFYfree (b);
		}

		pthread_mutex_unlock(&session->fifo->lock); /*rKA*/
		DSFYfree (session->fifo);

		pthread_cond_destroy (&session->fifo->cs);
		pthread_mutex_destroy (&session->fifo->lock);

	}

	pthread_mutex_destroy (&session->lock);
	DSFYfree (session);

}
示例#2
0
/* Initialize sound session, called once */
bool snd_init(struct despotify_session *ds)
{
	DSFYDEBUG ("Initializing sound FIFO etc (happens once)\n");

	DSFYDEBUG("Setting state to DL_FILLING\n");
	ds->dlstate = DL_FILLING;

	/* This is the fifo that will hold fragments of compressed audio */
        ds->fifo = calloc(1, sizeof(struct ds_snd_fifo));
        if (!ds->fifo)
		return false;
        ds->fifo->maxbytes = 1024 * 1024; /* 1 MB default buffer size */
        ds->fifo->watermark = 200 * 1024; /* 200 KB default watermark */

        if (pthread_mutex_init (&ds->fifo->lock, NULL)) {
            DSFYfree (ds->fifo);
            return NULL;
	}

	if (pthread_cond_init (&ds->fifo->cs, NULL)) {
            DSFYfree (ds->fifo);
		pthread_mutex_destroy (&ds->fifo->lock);
		return NULL;
	}

        return true;
}
示例#3
0
/* Reset for new song */
void snd_reset(struct despotify_session* ds)
{
    DSFYDEBUG("Setting state to DL_DRAINING\n");
    ds->fifo->totbytes = 0;
    ds->dlstate = DL_DRAINING;
    ov_clear(ds->vf);
    DSFYfree(ds->vf);
}
示例#4
0
void snd_reset_codec(struct despotify_session* ds) {
	DSFYDEBUG("Resetting audio codec\n");
	if ( ds->vf ) {
		ov_clear(ds->vf);
		DSFYfree(ds->vf);
	} else if ( ds->mf ) {
		mpg123_close(ds->mf);
		mpg123_delete(ds->mf);
		ds->mf = NULL;
	}
}
示例#5
0
文件: sndqueue.c 项目: estock/spot
/* Initialize sound session, called once */
snd_SESSION *snd_init (void)
{
	snd_SESSION *session;

	DSFYDEBUG ("snd_init(): Entering..\n");

	/* Init session struct */
	session = (snd_SESSION *) malloc (sizeof (snd_SESSION));
	if (!session)
		return NULL;

	session->vf = NULL;
	session->actx = NULL;
	session->dlstate = DL_IDLE;
	session->audio_request = NULL;
	session->audio_request_arg = NULL;
	session->buffer_threshold = BUFFER_THRESHOLD;
	session->audio_end = snd_stop;	/* Default is to stop the snd thread */
	session->time_tell = NULL;
	if (pthread_mutex_init (&session->lock, NULL)) {
		DSFYfree (session);

		return NULL;
	}

	/* This is the queue that will hold fragments of compressed audio */
	session->fifo = (oggFIFO *) malloc (sizeof (oggFIFO));
	if (!session->fifo) {
		pthread_mutex_destroy (&session->lock);
		DSFYfree (session);

		return NULL;
	}

	session->fifo->totbytes = 0;
	session->fifo->start = NULL;
	session->fifo->end = NULL;

	if (pthread_mutex_init (&session->fifo->lock, NULL)) {
		DSFYfree (session->fifo);

		pthread_mutex_destroy (&session->lock);
		DSFYfree (session);

		return NULL;
	}

	if (pthread_cond_init (&session->fifo->cs, NULL) != 0) {
		pthread_mutex_destroy (&session->fifo->lock);
		DSFYfree (session->fifo);

		pthread_mutex_destroy (&session->lock);
		DSFYfree (session);

		return NULL;
	}

	return session;
}
示例#6
0
文件: sndqueue.c 项目: arachsys/spot
void snd_reset_codec(struct despotify_session* ds) {
#ifdef DECODERS
	DSFYDEBUG("Resetting audio codec\n");
	if ( ds->vf ) {
		ov_clear(ds->vf);
		DSFYfree(ds->vf);
	} else if ( ds->mf ) {
#ifdef MP3_SUPPORT
		mpg123_close(ds->mf);
		mpg123_delete(ds->mf);
#endif
		ds->mf = NULL;
	}
#endif
}
示例#7
0
int snd_next(struct despotify_session *ds)
{
    pthread_mutex_lock(&ds->fifo->lock);

    /* go through fifo and look for next track */
    struct ds_snd_buffer* b;
    struct ds_snd_buffer* next;
    for (b = ds->fifo->start; b; b = next) {
        if (b->cmd == SND_CMD_START)
            break;

        if (b->ptr)
            free(b->ptr);
        ds->fifo->totbytes -= b->length;
        next = b->next;
        free(b);
    }

    ds->fifo->start = b;

    if (!b) {
        /* we didn't have next track in memory */
        ds->fifo->end = NULL;
        pthread_mutex_unlock(&ds->fifo->lock);
        return 0;
    }

    pthread_mutex_unlock(&ds->fifo->lock);

    /* notify client */
    if (ds->client_callback)
        ds->client_callback(ds, DESPOTIFY_NEW_TRACK,
                            b->ptr,
                            ds->client_callback_data);

    /* tell decoder to start over */
    ov_clear(ds->vf);
    DSFYfree(ds->vf);

    return 1;
}
示例#8
0
int snd_get_pcm(struct despotify_session* ds, struct ds_pcm_data* pcm)
{
    if (!ds || !ds->fifo || !ds->fifo->start) {
        pcm->len = 0;
        shortsleep();
        return 0;
    }

    /* top up fifo */
    snd_fill_fifo(ds);

    if (!ds->vf) {
        DSFYDEBUG ("Initializing vorbisfile struct\n");

        /* Allocate Vorbis struct */
        ds->vf = calloc(1, sizeof (OggVorbis_File));
        if (!ds->vf)
            return -1;

        /* Initialize Vorbis struct with the appropriate callbacks */
        ov_callbacks callbacks;
        callbacks.read_func = snd_ov_read_callback;
        callbacks.seek_func = seek_func;
        callbacks.close_func = NULL;
        callbacks.tell_func = NULL;

        /* Now call ov_open_callbacks(). This will trigger the read_func */
        _DSFYDEBUG("Calling ov_open_callbacks()\n");

        int ret = ov_open_callbacks(ds, ds->vf, NULL, 0, callbacks);
        if (ret) {
            DSFYfree(ds->vf);
            DSFYDEBUG("ov_open_callbacks(): error %d (%s)\n",
                      ret,
                      ret == OV_ENOTVORBIS? "not Vorbis":
                      ret == OV_EBADHEADER? "bad header":
                      "unknown, check <vorbis/codec.h>")
            return ret * 10;
        }
    }
示例#9
0
/* Destroy a sound session */
void snd_destroy (struct despotify_session* ds)
{
	DSFYDEBUG ("Destroying sound FIFO etc\n");

	/* Free the fifo */
	if (ds->fifo) {
		pthread_mutex_lock(&ds->fifo->lock);

		/* free buffers */
		while (ds->fifo->start) {
                        struct ds_snd_buffer* b = ds->fifo->start;
			ds->fifo->start = ds->fifo->start->next;
			free (b->ptr);
			free (b);
		}

                pthread_mutex_unlock(&ds->fifo->lock);
		pthread_cond_destroy(&ds->fifo->cs);
		pthread_mutex_destroy(&ds->fifo->lock);
                
		DSFYfree (ds->fifo);
	}
}
示例#10
0
文件: pulseaudio.c 项目: Voxar/spot
int pulseaudio_stop (AUDIOCTX * actx)
{
	pa_PRIVATE *priv = (pa_PRIVATE *) actx->driverprivate;

	assert (priv != NULL);

	/* Tell loop thread to exit */
	pthread_mutex_lock (&priv->lock);
	priv->state = PU_END;
        pthread_cond_wait (&priv->end, &priv->lock);
	pthread_mutex_unlock (&priv->lock);

        /* When the other loop has exited, free the non-audio
         * resources (memory, mutexes).
         */
        pthread_mutex_destroy (&priv->lock);
        pthread_cond_destroy (&priv->end);
        pthread_cond_destroy (&priv->pause);

        DSFYfree (actx->driverprivate);

	return 0;
}
示例#11
0
/*
 * Ogg-Vorbis read() callback
 * Called by both ov_info() and ov_read()
 *
 * This functions dequeues buffers from the fifo
 *
 */
size_t snd_ov_read_callback(void *ptr, size_t size, size_t nmemb, void* session)
{
    struct despotify_session* ds = session;

    pthread_mutex_lock(&ds->fifo->lock);

    int totlength = 0;
    bool loop = true;

    /* process data */
    while (loop) {
        /* Check queue status */
        if (ds->fifo->start == NULL) {
            _DSFYDEBUG ("Waiting for data (%d bytes)\n", ds->fifo->totbytes);
            pthread_cond_wait (&ds->fifo->cs, &ds->fifo->lock);
            _DSFYDEBUG ("Got data\n");
        }

        DSFYDEBUG_SNDQUEUE("Processing one buffer at ds->fifo->start."
                           " %zd items of size %zd requested. Totbytes: %d\n",
                           size, nmemb, ds->fifo->totbytes );

        struct ds_snd_buffer* b = ds->fifo->start;
        if (!b)
            break;

        _DSFYDEBUG("loop cmd:%d bytes:%d\n", b->cmd, ds->fifo->totbytes);

        switch (b->cmd)
        {
        case SND_CMD_START:
            /* first packet of a track */
            DSFYDEBUG ("Got SND_CMD_START\n");

            /* Increment by one */
            ds->fifo->start = ds->fifo->start->next;

            /* notify client */
            if (ds->client_callback)
                ds->client_callback(ds, DESPOTIFY_NEW_TRACK,
                                    b->ptr,
                                    ds->client_callback_data);
            /* If this was the last entry */
            if (b == ds->fifo->end)
                ds->fifo->end = NULL;
            if (b->ptr)
                DSFYfree (b->ptr);
            DSFYfree (b);
            break;

        case SND_CMD_DATA:
        {
            /* data packet */
            int remaining = b->length - b->consumed;
            int ptrsize = size * nmemb;
            int length;

            if (totlength + remaining < ptrsize)
                length = remaining;	/* The entire buffer will fit */
            else {
                length = ptrsize - totlength; /* Don't overrun ptrsize */
            }

            memcpy (ptr + totlength, b->ptr + b->consumed, length);

            b->consumed += length;
            totlength += length;

            /* If we have used the entire buffer, free it */
            if (b->consumed == b->length) {
                ds->fifo->start = ds->fifo->start->next;
                ds->fifo->totbytes -= b->length;

                /* If this was the last entry */
                if (b == ds->fifo->end)
                    ds->fifo->end = NULL;

                DSFYfree (b->ptr);
                DSFYfree (b);
            }

            /* exit if input is empty or output is full */
            if (!ds->fifo->start || totlength == (int)(size*nmemb))
                loop = false;
            break;
        }

        case SND_CMD_END:
            /* last packet of a track, return 0 bytes to signal EOF */
            DSFYDEBUG ("Got SND_CMD_END\n");

            /* if there already are bytes to return,
               send them first and then come back here empty */
            if (totlength) {
                loop = false;
                break;
            }

            /* Increment by one */
            ds->fifo->start = ds->fifo->start->next;

            /* If this was the last entry */
            if (b == ds->fifo->end)
                ds->fifo->end = NULL;

            /* If this was the last entry */
            if (b == ds->fifo->end)
                ds->fifo->end = NULL;
            if (b->ptr)
                DSFYfree (b->ptr);
            DSFYfree (b);

            _DSFYDEBUG("Calling despotify_end_of_track\n");

            if (!ds->fifo->start) {
                /* (snd_stop locks the mutex internally) */
                pthread_mutex_unlock(&ds->fifo->lock);
                snd_stop(ds);
                pthread_mutex_lock(&ds->fifo->lock);

                if (ds->client_callback)
                    ds->client_callback(ds, DESPOTIFY_END_OF_PLAYLIST,
                                        NULL, ds->client_callback_data);
            }
            /* return 0 bytes as EOF marker to decoder */
            loop = false;
            break;
        }
    }

    pthread_mutex_unlock(&ds->fifo->lock);

    /* Return number of bytes read to ogg-layer */
    _DSFYDEBUG("Returning %d bytes. %d left.\n",
               totlength, ds->fifo->totbytes);
    return totlength;
}
示例#12
0
文件: libao.c 项目: gusax/despotify
int libao_play (AUDIOCTX * actx)
{
	ao_device *device;
	ao_PRIVATE *priv = (ao_PRIVATE *) actx->driverprivate;
	bool quit = false;

	assert (priv != NULL);

	device = (ao_device *) priv->device;

	/* Driver loop */
	for (;;) {
		unsigned char buf[8192];
		ssize_t r;

		/* Fetch state lock */
		pthread_mutex_lock (&priv->lock);

		switch (priv->state) {
		case AO_END:
			quit = true;
			break;

		case AO_PAUSED:
			/* Wait for unpause signal */
			pthread_cond_wait (&priv->pause, &priv->lock);
			break;

		case AO_PLAYING:
		case AO_IDLE:
		default:
			break;
		}

		pthread_mutex_unlock (&priv->lock);

		if (quit)
			break;

		/* Read some data ... */
		r = pcm_read (actx->pcmprivate, (char *) buf, sizeof (buf), 0,
			      2, 1, NULL);

		if (r == OV_HOLE) {	/* vorbis got garbage */
			DSFYDEBUG ("pcm_read() == OV_HOLE\n");
			continue;
		}

		if (r <= 0) {
			DSFYDEBUG ("pcm_read() == %zd\n", r);
			if (r == 0)	/* EOF */
				break;
			exit (-1);
		}

		/* ... and play it */
		if (ao_play (device, (char *) buf, (int) r) == 0) {
			DSFYDEBUG ("ao_play() failed\n");
			exit (-1);
		}
	}

	if (ao_close (device) == 0) {
		DSFYDEBUG ("ao_close() failed\n");
		exit (-1);
	}

        pthread_mutex_destroy (&priv->lock);
        pthread_cond_destroy (&priv->pause);

        DSFYfree(actx->driverprivate);
	/* This will kill the thread */
	DSFYDEBUG ("libao thread exiting\n");
	return 0;
}