Esempio n. 1
0
	void* RunAudio()
	{
		while(true)
		{
			if (!paused)
			{
				memset(mixbuf, 0, mixlen);
				NativeMix((short *)mixbuf, mixlen / 4);

				fd_set rfds, wfds;
				int nflds;
				if (!paused && (FD_ISSET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds)))
				{
					snd_pcm_plugin_write(pcm_handle, mixbuf, mixlen);
				}
				FD_ZERO(&rfds);
				FD_ZERO(&wfds);

				FD_SET(snd_mixer_file_descriptor(mixer_handle), &rfds);
				FD_SET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds);
				nflds = std::max(snd_mixer_file_descriptor(mixer_handle), snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK));
				select (nflds+1, &rfds, &wfds, NULL, NULL);
			}
			else
				delay((AUDIO_SAMPLES*1000)/AUDIO_FREQ);
		}
	}
static int process_write(snd_pcm_t* hPlay)
{
    // calculate read chunk size to ensure a entire sample point (all channels)
    // is read
    size_t iReadChunkSize = sizeof(short) * (size_t)channels;
    size_t iNumReadChunks = (unsigned int)fragsize / iReadChunkSize;

    int nread = fread(inputdata, iReadChunkSize, iNumReadChunks, inputfile);
    nread *= (int)iReadChunkSize;
    if (nread <= 0) {
        cli_print("%s: stopping, end of input", __func__);
        return 1;
    }
    if (nread > 0) {
        int nwritten;
        // make it a full frag
        if (nread < fragsize) {
            memset(inputdata + nread, 0, (size_t)(fragsize - nread));
        }
        nwritten = snd_pcm_plugin_write(hPlay, inputdata, (size_t)fragsize);
        if (nwritten != fragsize) {
            cli_print("snd_pcm_plugin_write: %s", snd_strerror(nwritten));
            return 1;
        }
    }
    return 0;
}
Esempio n. 3
0
void *Audio_ALSA::write ()
{
    if (_audioHandle == NULL)
    {
        _errorString = "ERROR: Device not open.";
        return NULL;
    }

    snd_pcm_plugin_write (_audioHandle, _sampleBuffer, _settings.bufSize);
    return (void *) _sampleBuffer;
}
Esempio n. 4
0
void *Audio_ALSA::write ()
{
    if (_audioHandle == NULL)
    {
        _errorString = "ERROR: Device not open.";
        return NULL;
    }

#ifdef HAVE_ALSA_ASOUNDLIB_H
    if (snd_pcm_writei  (_audioHandle, _sampleBuffer, _settings.bufSize / _alsa_to_frames_divisor) == -EPIPE)
        snd_pcm_prepare (_audioHandle); // Underrun
#else // Obsolete interface
    snd_pcm_plugin_write (_audioHandle, _sampleBuffer, _settings.bufSize);
#endif
    return (void *) _sampleBuffer;
}
Esempio n. 5
0
static int alsa_dsp_write(struct sysdep_dsp_struct *dsp, unsigned char *data,
   int count)
{
	int BytesWritten, BytesToWrite;
        unsigned int bytesleft;
        int err;
	struct alsa_dsp_priv_data *priv = dsp->_priv;
        snd_pcm_channel_status_t  status = {0};

	BytesToWrite = count*alsa_dsp_bytes_per_sample[dsp->hw_info.type];
	BytesWritten = snd_pcm_plugin_write( priv->audio_dev.m_AudioHandle, data, BytesToWrite );
#if 0	
	if (BytesWritten == 0)
        {
		return count;
        }
#endif	
	return BytesWritten / alsa_dsp_bytes_per_sample[dsp->hw_info.type];
}
Esempio n. 6
0
File: qsa.c Progetto: Atom66/tain335
static int write_qsa(audio_output_t* ao, unsigned char* buf, int bytes)
{
    int written;
    int status;
    snd_pcm_channel_status_t cstatus;
    qsa_internal_t* userptr;

    userptr=ao->userptr;
    if (userptr!=NULL);
    {
        written=snd_pcm_plugin_write(userptr->audio_handle, buf, bytes);
        if (written!=bytes)
        {
            /* Check if samples playback got stuck somewhere in hardware or in */
            /* the audio device driver */
            if ((errno==EAGAIN) && (written==0))
            {
                return 0;
            }
            if ((errno==EINVAL) || (errno==EIO))
            {
                memset(&cstatus, 0, sizeof(cstatus));
                cstatus.channel=SND_PCM_CHANNEL_PLAYBACK;
                status=snd_pcm_plugin_status(userptr->audio_handle, &cstatus);
                if (status>0)
                {
                    return 0;
                }
                if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) ||
                    (cstatus.status == SND_PCM_STATUS_READY))
                {
                    status=snd_pcm_plugin_prepare(userptr->audio_handle, SND_PCM_CHANNEL_PLAYBACK);
                    if (status<0)
                    {
                        return 0;
                    }
                }
            }
        }
    }

    return written;
}
Esempio n. 7
0
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
 * timed mods) of audio data to the output device.
 */
static void bufdump(struct xmp_context *ctx, int i)
{
	void *b;

	b = xmp_smix_buffer(ctx);
	/* Note this assumes a fragment size of (frag_size) */
	while (i > 0) {
		size_t f = (frag_size) - (mybuffer_nextfree - mybuffer);
		size_t to_copy = (f < i) ? f : i;

		memcpy(mybuffer_nextfree, b, to_copy);
		b += to_copy;
		mybuffer_nextfree += to_copy;
		f -= to_copy;
		i -= to_copy;
		if (f == 0) {
			snd_pcm_plugin_write(pcm_handle, mybuffer, frag_size);
			mybuffer_nextfree = mybuffer;
		}
	}
}
/**
 * setup play based on the audio sample wave
 */
static int play(circular_buffer_t* circular_buffer) {

	// If there's nothing in the circular buffer play the sound of silence
	// In the real world you may well play the last frame you received. There are algorithms DSP experts know about apparently
	char* silence_buffer = (char*) malloc(g_frame_size_p);
	memset(silence_buffer, SILENCE, g_frame_size_p);

	// Data read from the circular buffer
	char* play_buffer = (char*) malloc(g_frame_size_p);
	memset(play_buffer, 0, g_frame_size_p);

	// Diagnostics
	int total_written = 0;
	int failed = 0;
	int capture_not_ready = 0;
	// Loop till stopAudio() flags us
	while (g_execute_audio) {
		int written;
		// Read the circular buffer
		// returns true only if there is data to satisfy frame_size
		if (!capture_ready) {
			++capture_not_ready;
			written = snd_pcm_plugin_write(g_pcm_handle_p, play_buffer,
					g_frame_size_p);
			if (written < 0 || written != g_frame_size_p) {
				fprintf(stderr,"PLAY RESET 1\n");
				resetPlay();
			}else{
				total_written += written;
			}

		} else if (readFromCircularBuffer(circular_buffer, play_buffer,
				g_frame_size_p)) {
			written = snd_pcm_plugin_write(g_pcm_handle_p, play_buffer,
					g_frame_size_p);
			if (written < 0 || written != g_frame_size_p) {
				fprintf(stderr,"PLAY RESET 2\n");
				resetPlay();
			}else{
				total_written += written;
			}

		} else {
			// You would expect the jitter buffer to be possibly empty at startup because threads are not synchronized
			// increasing the frags_max reduces the occurrences of failure here
			// On the simulator it always fails written = 0 presumably meaning an overrun
			written = snd_pcm_plugin_write(g_pcm_handle_p, silence_buffer,
					g_frame_size_p);
			if (written < 0 || written != g_frame_size_p) {
				fprintf(stderr,"PLAY RESET 3\n");
				resetPlay();
			}
			failed++;
		}
	}
	fprintf(stderr,"PLAY EXIT BEGIN\n");
	(void) snd_pcm_plugin_flush(g_pcm_handle_p, SND_PCM_CHANNEL_PLAYBACK);
	(void) snd_pcm_close(g_pcm_handle_p);
	audio_manager_free_handle(g_audio_manager_handle_p);
	free(play_buffer);
	free(silence_buffer);
	fprintf(stderr,"PLAY EXIT Total Bytes written = %d failed = %d capture_not_ready %d\n",total_written,failed,capture_not_ready);
	return 0;
}
Esempio n. 9
0
static void dump_buffer ()
{
	snd_pcm_plugin_write (pcm_handle, buffer, BUFFER_SIZE << 1);
}
Esempio n. 10
0
static void
QSA_PlayDevice(_THIS)
{
    snd_pcm_channel_status_t cstatus;
    int written;
    int status;
    int towrite;
    void *pcmbuffer;

    if ((!this->enabled) || (!this->hidden)) {
        return;
    }

    towrite = this->spec.size;
    pcmbuffer = this->hidden->pcm_buf;

    /* Write the audio data, checking for EAGAIN (buffer full) and underrun */
    do {
        written =
            snd_pcm_plugin_write(this->hidden->audio_handle, pcmbuffer,
                                 towrite);
        if (written != towrite) {
            /* Check if samples playback got stuck somewhere in hardware or in */
            /* the audio device driver */
            if ((errno == EAGAIN) && (written == 0)) {
                if (this->hidden->timeout_on_wait != 0) {
                    SDL_SetError("QSA: buffer playback timeout");
                    return;
                }
            }

            /* Check for errors or conditions */
            if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
                /* Let a little CPU time go by and try to write again */
                SDL_Delay(1);

                /* if we wrote some data */
                towrite -= written;
                pcmbuffer += written * this->spec.channels;
                continue;
            } else {
                if ((errno == EINVAL) || (errno == EIO)) {
                    SDL_memset(&cstatus, 0, sizeof(cstatus));
                    if (!this->hidden->iscapture) {
                        cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
                    } else {
                        cstatus.channel = SND_PCM_CHANNEL_CAPTURE;
                    }

                    status =
                        snd_pcm_plugin_status(this->hidden->audio_handle,
                                              &cstatus);
                    if (status < 0) {
                        QSA_SetError("snd_pcm_plugin_status", status);
                        return;
                    }

                    if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) ||
                        (cstatus.status == SND_PCM_STATUS_READY)) {
                        if (!this->hidden->iscapture) {
                            status =
                                snd_pcm_plugin_prepare(this->hidden->
                                                       audio_handle,
                                                       SND_PCM_CHANNEL_PLAYBACK);
                        } else {
                            status =
                                snd_pcm_plugin_prepare(this->hidden->
                                                       audio_handle,
                                                       SND_PCM_CHANNEL_CAPTURE);
                        }
                        if (status < 0) {
                            QSA_SetError("snd_pcm_plugin_prepare", status);
                            return;
                        }
                    }
                    continue;
                } else {
                    return;
                }
            }
        } else {
            /* we wrote all remaining data */
            towrite -= written;
            pcmbuffer += written * this->spec.channels;
        }
    } while ((towrite > 0) && (this->enabled));

    /* If we couldn't write, assume fatal error for now */
    if (towrite != 0) {
        this->enabled = 0;
    }
}
Esempio n. 11
0
FORCE_ALIGN static int qsa_proc_playback(void* ptr)
{
    ALCdevice* device=(ALCdevice*)ptr;
    qsa_data* data=(qsa_data*)device->ExtraData;
    char* write_ptr;
    int avail;
    snd_pcm_channel_status_t status;
    struct sched_param param;
    fd_set wfds;
    int selectret;
    struct timeval timeout;

    SetRTPriority();
    althrd_setname(althrd_current(), MIXER_THREAD_NAME);

    /* Increase default 10 priority to 11 to avoid jerky sound */
    SchedGet(0, 0, &param);
    param.sched_priority=param.sched_curpriority+1;
    SchedSet(0, 0, SCHED_NOCHANGE, &param);

    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);

    while (!data->killNow)
    {
        ALint len=data->size;
        write_ptr=data->buffer;

        avail=len/frame_size;
        aluMixData(device, write_ptr, avail);

        while (len>0 && !data->killNow)
        {
            FD_ZERO(&wfds);
            FD_SET(data->audio_fd, &wfds);
            timeout.tv_sec=2;
            timeout.tv_usec=0;

            /* Select also works like time slice to OS */
            selectret=select(data->audio_fd+1, NULL, &wfds, NULL, &timeout);
            switch (selectret)
            {
                case -1:
                     aluHandleDisconnect(device);
                     return 1;
                case 0:
                     break;
                default:
                     if (FD_ISSET(data->audio_fd, &wfds))
                     {
                         break;
                     }
                     break;
            }

            int wrote=snd_pcm_plugin_write(data->pcmHandle, write_ptr, len);

            if (wrote<=0)
            {
                if ((errno==EAGAIN) || (errno==EWOULDBLOCK))
                {
                    continue;
                }

                memset(&status, 0, sizeof (status));
                status.channel=SND_PCM_CHANNEL_PLAYBACK;

                snd_pcm_plugin_status(data->pcmHandle, &status);

                /* we need to reinitialize the sound channel if we've underrun the buffer */
                if ((status.status==SND_PCM_STATUS_UNDERRUN) ||
                    (status.status==SND_PCM_STATUS_READY))
                {
                    if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0)
                    {
                        aluHandleDisconnect(device);
                        break;
                    }
                }
            }
            else
            {
                write_ptr+=wrote;
                len-=wrote;
            }
        }
    }

    return 0;
}
Esempio n. 12
0
/**
 * Play audio received from PJMEDIA
 */
static int pb_thread_func (void *arg)
{
    struct bb10_stream* stream = (struct bb10_stream *) arg;
    /* Handle from bb10_open_playback */
    /* Will be 640 */
    int size                   	= stream->pb_buf_size;
    /* 160 frames for 20ms */
    unsigned long nframes	= stream->pb_frames;
    void *user_data            	= stream->user_data;
    char *buf 		       	= stream->pb_buf;
    pj_timestamp tstamp;
    int result = 0;

    pj_bzero (buf, size);
    tstamp.u64 = 0;

    TRACE_((THIS_FILE, "pb_thread_func: size = %d ", size));

    /* Do the final initialization now the thread has started. */
    if ((result = snd_pcm_plugin_prepare(stream->pb_pcm,
                                         SND_PCM_CHANNEL_PLAYBACK)) < 0)
    {
        close_play_pcm(stream);
        TRACE_((THIS_FILE, "pb_thread_func failed prepare = %d", result));
	return PJ_SUCCESS;
    }

    while (!stream->quit) {
        pjmedia_frame frame;

        frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
        /* pointer to buffer filled by PJMEDIA */
        frame.buf = buf;
        frame.size = size;
        frame.timestamp.u64 = tstamp.u64;
        frame.bit_info = 0;

        result = stream->pb_cb (user_data, &frame);
        if (result != PJ_SUCCESS || stream->quit)
            break;

        if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
            pj_bzero (buf, size);

        /* Write 640 to play unit */
        result = snd_pcm_plugin_write(stream->pb_pcm,buf,size);
        if (result != size || result < 0) {
            snd_pcm_channel_status_t status;
            if (snd_pcm_plugin_status (stream->pb_pcm, &status) < 0) {
                PJ_LOG(4,(THIS_FILE,
                	  "underrun: playback channel status error"));
                continue;
            }

            if (status.status == SND_PCM_STATUS_READY ||
        	status.status == SND_PCM_STATUS_UNDERRUN)
            {
                if (snd_pcm_plugin_prepare (stream->pb_pcm,
                                            SND_PCM_CHANNEL_PLAYBACK) < 0)
                {
                    PJ_LOG(4,(THIS_FILE,
                    	      "underrun: playback channel prepare error"));
                    continue;
                }
            }

            TRACE_((THIS_FILE, "pb_thread_func failed write = %d", result));
        }

	tstamp.u64 += nframes;
    }

    flush_play(stream);
    close_play_pcm(stream);
    TRACE_((THIS_FILE, "pb_thread_func: Stopped"));

    return PJ_SUCCESS;
}
Esempio n. 13
0
void AudioDriverBB10::thread_func(void *p_udata) {

	AudioDriverBB10 *ad = (AudioDriverBB10 *)p_udata;

	int channels = speaker_mode;
	int frame_count = ad->sample_buf_count / channels;
	int bytes_out = frame_count * channels * 2;

	while (!ad->exit_thread) {

		if (!ad->active) {

			for (int i = 0; i < ad->sample_buf_count; i++) {

				ad->samples_out[i] = 0;
			};
		} else {

			ad->lock();

			ad->audio_server_process(frame_count, ad->samples_in);

			ad->unlock();

			for (int i = 0; i < frame_count * channels; i++) {

				ad->samples_out[i] = ad->samples_in[i] >> 16;
			}
		};

		int todo = bytes_out;
		int total = 0;

		while (todo) {

			uint8_t *src = (uint8_t *)ad->samples_out;
			int wrote = snd_pcm_plugin_write(ad->pcm_handle, (void *)(src + total), todo);
			if (wrote < 0) {
				// error?
				break;
			};
			total += wrote;
			todo -= wrote;
			if (wrote < todo) {
				if (ad->thread_exited) {
					break;
				};
				printf("pcm_write underrun %i, errno %i\n", (int)ad->thread_exited, errno);
				snd_pcm_channel_status_t status;
				zeromem(&status, sizeof(status));
				// put in non-blocking mode
				snd_pcm_nonblock_mode(ad->pcm_handle, 1);
				status.channel = SND_PCM_CHANNEL_PLAYBACK;
				int ret = snd_pcm_plugin_status(ad->pcm_handle, &status);
				//printf("status return %i, %i, %i, %i, %i\n", ret, errno, status.status, SND_PCM_STATUS_READY, SND_PCM_STATUS_UNDERRUN);
				snd_pcm_nonblock_mode(ad->pcm_handle, 0);
				if (ret < 0) {
					break;
				};
				if (status.status == SND_PCM_STATUS_READY ||
						status.status == SND_PCM_STATUS_UNDERRUN) {
					snd_pcm_plugin_prepare(ad->pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
				} else {
					break;
				};
			};
		};
	};

	snd_pcm_plugin_flush(ad->pcm_handle, SND_PCM_CHANNEL_PLAYBACK);

	ad->thread_exited = true;
	printf("**************** audio thread exit\n");
};
Esempio n. 14
0
int
main(int argc, char **argv)
{
    FILE *file;
    int  samples;
    char *sample_buffer;

    int rtn, final_return_code = -1, exit_application = 0;

    int bsize, bytes_read, total_written = 0;
    fd_set rfds, wfds;
    char input_file[PATH_MAX];
    char cwd[PATH_MAX];


    /*
     * Before we can listen for events from the BlackBerry Tablet OS platform
     * services, we need to initialize the BPS infrastructure
     */
    bps_initialize();

    if (setup_screen() != EXIT_SUCCESS) {
        printf("Unable to set up the screen. Exiting.");
        exit(-1);
    }

    /*
     * Once the BPS infrastructure has been initialized we can register for
     * events from the various BlackBerry Tablet OS platform services. The
     * Navigator service manages and delivers application life cycle and
     * visibility events.
     *
     * For this sample, we request Navigator events so we can track when
     * the system is terminating the application (NAVIGATOR_EXIT event).
     * This allows us to clean up application resources.
     * 
     * We request Audio Device events because we want to make sure that
     * we properly handle changes in audio output.
     *
     * We request dialog events to properly initialize the dialog
     * subsystem in order to display status and error messages.  
     */
    if (BPS_SUCCESS != navigator_request_events(0)) {
        fprintf(stderr, "Error requesting navigator events: %s", strerror(errno));
        exit(-1);
    }

    if (BPS_SUCCESS != dialog_request_events(0)) {
        fprintf(stderr, "Error requesting dialog events: %s", strerror(errno));
        exit(-1);
    }

    if (BPS_SUCCESS != audiodevice_request_events(0)) {
        fprintf(stderr, "Error requesting audio device events: %s", strerror(errno));
        exit(-1);
    }

    /*
     * Create and display the dialog.
     */
    create_dialog();

    /*
     * Open and check the input file.
     */
    getcwd(cwd, PATH_MAX);
    rtn = snprintf(input_file, PATH_MAX, "%s/%s", cwd, WAV_RELATIVE_PATH);
    if (rtn > PATH_MAX - 1) {
        err("File name and path too long");
        goto fail1;
    }

    if ((file = fopen(input_file, "r")) == 0) {
        err("File open failed");
        goto fail1;
    }

    if (check_hdr(file) == -1) {
        err("check_hdr failed");
        goto fail2;
    }

    /*
     * Parse the headers in the wav file to figure out what kind of data we
     * are dealing with in the file.
     */
    samples = find_tag(file, "fmt ");
    fread(&wav_header, sizeof(wav_header), 1, file);
    fseek(file,(samples - sizeof(wave_hdr)), SEEK_CUR);

    sample_rate = ENDIAN_LE32(wav_header.samples_per_sec);
    sample_channels = ENDIAN_LE16(wav_header.channels);
    sample_bits = ENDIAN_LE16(wav_header.bits_per_sample);

    snprintf(msg, MSG_SIZE, "SampleRate = %d, channels = %d, SampleBits = %d\n", sample_rate, sample_channels,
        sample_bits);
    show_dialog_message(msg);

    if (setup_snd(NULL)) {
        goto fail2;
    }

    bsize = setup.buf.block.frag_size;
    samples = find_tag(file, "data");
    sample_buffer = malloc(bsize);
    if (!sample_buffer) {
        goto fail3;
    }

    FD_ZERO(&rfds);
    FD_ZERO(&wfds);
    bytes_read = 1;
    while (total_written < samples && bytes_read > 0 ) {
        bps_event_t *event = NULL;

        while (BPS_SUCCESS == bps_get_event(&event, 0) && event) {
            /*
             * If it is a NAVIGATOR_EXIT event then we are done so stop
             * processing events, clean up and exit
             */
            if (bps_event_get_domain(event) == navigator_get_domain()) {
                if (NAVIGATOR_EXIT == bps_event_get_code(event)) {
                    exit_application = 1;
                    goto success;
                }
            }

            if (bps_event_get_domain(event) == audiodevice_get_domain()) {
                /*
                 * If it is a audio device event then it means a new audio device
                 * has been enabled and a switch is required.  We close the old,
                 * open the new audio device using the path and get the card number so
                 * that we can close and re-open the mixer with the new card
                 * number.
                 */

                const char * audiodevice_path = audiodevice_event_get_path(event);

                if (NULL == audiodevice_path) {
                    snprintf(msg, MSG_SIZE, "audiodevice_event_get_path failed: %s\n", snd_strerror(rtn));
                    show_dialog_message(msg);
                    goto fail5;
                }

                if ((rtn = snd_mixer_close(mixer_handle)) < 0) {
                    snprintf(msg, MSG_SIZE, "snd_mixer_close failed: %s\n", snd_strerror(rtn));
                    show_dialog_message(msg);
                    goto fail4;
                }

                if ((rtn = snd_pcm_close(pcm_handle)) < 0) {
                    snprintf(msg, MSG_SIZE, "snd_pcm_close failed: %s\n", snd_strerror(rtn));
                    show_dialog_message(msg);
                    goto fail3;
                }

                if (setup_snd(audiodevice_path)) {
                    /*
                     * setup_snd() closes pcm and mixer handles in the case of error so we
                     * skip clean up of the handles in the case of failure.
                     */
                    goto fail3;
                }
            }
        }

        if (tcgetpgrp(0) == getpid())
            FD_SET(STDIN_FILENO, &rfds);
        FD_SET(snd_mixer_file_descriptor(mixer_handle), &rfds);
        FD_SET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds);

        rtn = max(snd_mixer_file_descriptor(mixer_handle),
                   snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK));

        if (select(rtn + 1, &rfds, &wfds, NULL, NULL) == -1) {
            err("select");
            goto fail5;
        }

        if (FD_ISSET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds)) {
            snd_pcm_channel_status_t status;
            int written = 0;

            if ((bytes_read = fread(sample_buffer, 1, min(samples - total_written, bsize), file)) <= 0)
                continue;
            written = snd_pcm_plugin_write(pcm_handle, sample_buffer, bytes_read);
            if (written < bytes_read) {
                memset(&status, 0, sizeof(status));
                status.channel = SND_PCM_CHANNEL_PLAYBACK;
                if (snd_pcm_plugin_status(pcm_handle, &status) < 0) {
                    show_dialog_message("underrun: playback channel status error\n");
                    goto fail5;
                }

                if (status.status == SND_PCM_STATUS_READY ||
                    status.status == SND_PCM_STATUS_UNDERRUN) {
                    if (snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK) < 0) {
                        show_dialog_message("underrun: playback channel prepare error\n");
                        goto fail5;
                    }
                }
                if (written < 0)
                    written = 0;
                written += snd_pcm_plugin_write(pcm_handle, sample_buffer + written, bytes_read - written);
            }
            total_written += written;
        }
    }

success:
    bytes_read = snd_pcm_plugin_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
    final_return_code = 0;
    /*
     * there are return codes to these close calls, but we would do the same
     * thing regardless of error or success so we do not check the return codes.
     */
fail5:
    snd_mixer_close(mixer_handle);
fail4:
    snd_pcm_close(pcm_handle);
fail3:
    free(sample_buffer);
    sample_buffer = NULL;
fail2:
    fclose(file);
fail1:


    while (!exit_application) {
        /*
         * Something went wrong so there is probably an error message and
         * we don't want to exit right away because we want the user to see
         * the message in the dialog.
         *
         * Using a negative timeout (-1) in the call to bps_get_event(...)
         * ensures that we don't busy wait by blocking until an event is
         * available.
         */
        bps_event_t *event = NULL;
        bps_get_event(&event, -1);

        if (event) {
            /*
             * If it is a NAVIGATOR_EXIT event then we are done so stop
             * processing events, clean up and exit
             */
            if (bps_event_get_domain(event) == navigator_get_domain()) {
                if (NAVIGATOR_EXIT == bps_event_get_code(event)) {
                    exit_application = 1;
                }
            }
        }
    }

    /*
     * Destroy the dialog, if it exists and cleanup screen resources.
     */
    destroy_dialog();
    cleanup_screen();
    bps_shutdown();

    return final_return_code;
}
Esempio n. 15
0
/* Plays a sound with the Advanced Linux Sound Architecture, ALSA.
   Returns 0 on successful playback, nonzero on error. */
int PlayerALSA(u_int8_t *samples, unsigned int bits, unsigned int channels,
               unsigned int rate, unsigned int bytes)
{
    int i;

    /* ALSA is a bit verbose, and it tends to require
       lots of structures. */
    unsigned int alsa_device = 0, alsa_card = 0;
    char *alsa_card_name;
    snd_ctl_t *alsa_ctl;
    snd_ctl_hw_info_t alsa_hw_info;
    snd_pcm_t *alsa_pcm;
    snd_pcm_channel_params_t alsa_params;
	
    /* Playback status variables. */
    unsigned int position;

    /* Scan for ALSA cards and devices. Each card has an integer ID
       less than snd_cards(). We scan for the first available card
       in order to demonstrate ALSA's organization, but we could
       find the default card and PCM device numbers immediately with
       the snd_defaults_pcm_card(), snd_defaults_pcm_device() functions. */
    alsa_pcm = NULL;
    for (alsa_card = 0; alsa_card < (unsigned)snd_cards(); alsa_card++) {

	/* Try to open this card. */
	if (snd_ctl_open(&alsa_ctl,alsa_card) < 0)
	    continue;
		
	/* Retrieve card info. */
	if (snd_ctl_hw_info(alsa_ctl,&alsa_hw_info) < 0) {
	    snd_ctl_close(alsa_ctl);
	    continue;
	}
		
	snd_ctl_close(alsa_ctl);
		
	/* Find a suitable device on this card. */
	alsa_pcm = NULL;
	for (alsa_device = 0; alsa_device < alsa_hw_info.pcmdevs; alsa_device++) {
	    if (snd_pcm_open(&alsa_pcm,alsa_card,
			     alsa_device,SND_PCM_OPEN_PLAYBACK) < 0) continue;
	    
	    /* Device successfully opened. */
	    break;
	}
		
	if (alsa_pcm != NULL) break;
    }
	
    /* Were we able to open a device? */
    if (alsa_card == (unsigned)snd_cards()) {
	printf("ALSA player: unable to find a configured device.\n");
	return -1;
    }
	
    /* Print info about the device. */
    if (snd_card_get_longname(alsa_card,&alsa_card_name) < 0)
	alsa_card_name = "(unknown)";
    printf("ALSA player: using device %i:%i (%s)\n",
	   alsa_card, alsa_device, alsa_card_name);
	
    /* Configure the device for the loaded sound data. */
    memset(&alsa_params,0,sizeof (alsa_params));
    alsa_params.channel = SND_PCM_CHANNEL_PLAYBACK;

    /* Use stream mode. In this mode, we don't have to give ALSA complete
       blocks; we can send it data as we get it. Block mode is needed for
       mmap() functionality. Unlike OSS, ALSA's mmap() functionality is
       quite reliable, and easily accessible through library functions.
       We won't use it here, though; there's no need. */
    alsa_params.mode = SND_PCM_MODE_STREAM;
    alsa_params.format.interleave = 1;
    
    /* We'll assume little endian samples. You may wish to use the data in
       the GNU C Library's endian.h to support other endiannesses. We're
       ignoring that case for simplicity. */
    if (bits == 8)
	alsa_params.format.format = SND_PCM_SFMT_U8;
    else if (bits == 16)
	alsa_params.format.format = SND_PCM_SFMT_S16_LE;
    else {
	printf("ALSA player: invalid sample size.\n");
	return -1;
    }
    alsa_params.format.rate = rate;
    alsa_params.format.voices = channels;
    alsa_params.start_mode = SND_PCM_START_DATA;
    alsa_params.stop_mode = SND_PCM_STOP_ROLLOVER;
    alsa_params.buf.block.frag_size = 4096;
    alsa_params.buf.block.frags_min = 1;
    alsa_params.buf.block.frags_max = 2;
	
    if ((i = snd_pcm_plugin_params(alsa_pcm,&alsa_params)) < 0) {
	printf("ALSA player: unable to set parameters.\n");
	snd_pcm_close(alsa_pcm);
	return -1;
    }

    if (snd_pcm_plugin_prepare(alsa_pcm, SND_PCM_CHANNEL_PLAYBACK) < 0) {
	printf("ALSA player: unable to prepare playback.\n");
	snd_pcm_close(alsa_pcm);
	return -1;
    }
	
    /* Feed the sound data to ALSA. */
    position = 0;
    while (position < bytes) {
	int written, blocksize;
		
	if (bytes-position < 4096)
	    blocksize = bytes-position;
	else
	    blocksize = 4096;
		
	/* Write to the sound device. */
	written = snd_pcm_plugin_write(alsa_pcm, &samples[position], blocksize);

	/* If ALSA can't take any more data right now, it'll return -EAGAIN.
	   If this were sound code for a game, we'd probably just contine the
	   game loop and try to write data the next time around.
	   In a game, you'd probably also want to put the device in nonblocking
	   mode (see the snd_pcm_nonblock_mode() function). */
	if (written == -EAGAIN) {
	    /* Waste some time. This keeps us from using 100% CPU. */
	    usleep(1000);

	    written = 0;
	} else {
	    if (written < 0) {
		perror("\nALSA player: error writing to sound device");
		snd_pcm_close(alsa_pcm);
		return -1;
	    }
	}

	/* Update the position. */
	position += written;

	/* Print some information. */
	WritePlaybackStatus(position, bytes, channels, bits, rate);
	printf("\r");
	fflush(stdout);
    }

    printf("\n");

    /* Wait until ALSA's internal buffers are empty, then stop playback.
       This will make sure that the entire sound clip has played. */
    snd_pcm_channel_flush(alsa_pcm, SND_PCM_CHANNEL_PLAYBACK);
    snd_pcm_close(alsa_pcm);

    return 0;
}
Esempio n. 16
0
static void NTO_PlayAudio(_THIS)
{
    int written, rval;
    int towrite;
    void* pcmbuffer;

    if (!this->enabled)
    {
        return;
    }
    
    towrite = this->spec.size;
    pcmbuffer = pcm_buf;

    /* Write the audio data, checking for EAGAIN (buffer full) and underrun */
    do {
        written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite);
        if (written != towrite)
        {
            if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
            {
                /* Let a little CPU time go by and try to write again */
                SDL_Delay(1);
                /* if we wrote some data */
                towrite -= written;
                pcmbuffer += written * this->spec.channels;
                continue;
            }		
            else
            {
                if ((errno == EINVAL) || (errno == EIO))
                {
                    SDL_memset(&cstatus, 0, sizeof(cstatus));
                    cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
                    if ((rval = snd_pcm_plugin_status(audio_handle, &cstatus)) < 0)
                    {
                        SDL_SetError("NTO_PlayAudio(): snd_pcm_plugin_status failed: %s\n", snd_strerror(rval));
                        return;
                    }	
                    if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY))
                    {
                        if ((rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
                        {
                            SDL_SetError("NTO_PlayAudio(): snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rval));
                            return;
                        }
                    }		        		
                    continue;
                }
                else
                {
                    return;
                }
            }
        }
        else
        {
            /* we wrote all remaining data */
            towrite -= written;
            pcmbuffer += written * this->spec.channels;
        }
    } while ((towrite > 0)  && (this->enabled));

    /* If we couldn't write, assume fatal error for now */
    if (towrite != 0)
    {
        this->enabled = 0;
    }

    return;
}
Esempio n. 17
0
/**
 * Play audio received from PJMEDIA
 */
static int pb_thread_func (void *arg)
{
    struct bb10_stream* stream = (struct bb10_stream *) arg;
    int size                   	= stream->pb_buf_size;
    unsigned long nframes	= stream->pb_frames;
    void *user_data            	= stream->user_data;
    char *buf 		       	= stream->pb_buf;
    pj_timestamp tstamp;
    int result = 0;
    int policy;
    struct sched_param param;

    TRACE_((THIS_FILE, "pb_thread_func: size = %d ", size));

    if (pthread_getschedparam(pthread_self(), &policy, &param) == 0) {
	param.sched_priority = 18;
	pthread_setschedparam (pthread_self(), policy, &param);
    }

    pj_bzero (buf, size);
    tstamp.u64 = 0;

    /* Do the final initialization now the thread has started. */
    if ((result = snd_pcm_plugin_prepare(stream->pb_pcm,
                                         SND_PCM_CHANNEL_PLAYBACK)) < 0)
    {
        TRACE_((THIS_FILE, "pb_thread_func failed prepare = %d", result));
        return PJ_SUCCESS;
    }

    while (!stream->quit) {
        pjmedia_frame frame;

        frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
        /* pointer to buffer filled by PJMEDIA */
        frame.buf = buf;
        frame.size = size;
        frame.timestamp.u64 = tstamp.u64;
        frame.bit_info = 0;

        /* Read the audio from pjmedia */
        result = stream->pb_cb (user_data, &frame);
        if (result != PJ_SUCCESS || stream->quit)
            break;

        if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
            pj_bzero (buf, size);

        /* Write 640 to play unit */
        result = snd_pcm_plugin_write(stream->pb_pcm,buf,size);
        if (result != size || result < 0) {
	    /* either the write to output device has failed or not the
	     * full amount of bytes have been written. This usually happens
	     * when audio routing is being changed by another thread
	     * Use a status variable for reading the error
	     */
	    snd_pcm_channel_status_t status;
            status.channel = SND_PCM_CHANNEL_PLAYBACK;
            if (snd_pcm_plugin_status (stream->pb_pcm, &status) < 0) {
                /* Call has failed nothing we can do except log and
                 * continue */
            	PJ_LOG(4,(THIS_FILE,
                	  "underrun: playback channel status error"));
            } else {
            	/* The status of the error has been read
            	 * RIM say these are expected so we can "re-prepare" the stream
            	 */
            	PJ_LOG(4,(THIS_FILE,"PLAY thread ERROR status = %d",
            		  status.status));
		if (status.status == SND_PCM_STATUS_READY ||
		    status.status == SND_PCM_STATUS_UNDERRUN ||
		    status.status == SND_PCM_STATUS_ERROR )
		{
		    if (snd_pcm_plugin_prepare (stream->pb_pcm,
						SND_PCM_CHANNEL_PLAYBACK) < 0)
		    {
			PJ_LOG(4,(THIS_FILE,
				  "underrun: playback channel prepare error"));
		    }
		}
	    }
        }
	tstamp.u64 += nframes;
    }

    flush_play(stream);
    TRACE_((THIS_FILE, "pb_thread_func: Stopped"));

    return PJ_SUCCESS;
}
Esempio n. 18
0
int audio_write_alsa(cst_audiodev *ad, void *samples, int num_bytes)
{
    snd_pcm_t *pcm = ad->platform_data;

    return snd_pcm_plugin_write(pcm,samples,num_bytes);
}
Esempio n. 19
0
int
main (int argc, char **argv)
{
    int     card = -1;
    int     dev = 0;
    snd_pcm_t *pcm_handle;
    FILE   *file;
    wave_hdr wav_header;
    int     samples;
    int     sample_rate;
    int     sample_channels;
    int     sample_bits;
    char   *sample_buffer;
    int     fragsize = -1;
    int     verbose = 0;

    int     rtn;
    int     final_return_code = -1;
    snd_pcm_channel_info_t pi;
    snd_mixer_t *mixer_handle;
    snd_mixer_group_t group;
    snd_pcm_channel_params_t pp;
    snd_pcm_channel_setup_t setup;
    int     bsize, bytes_read, total_written = 0;
    fd_set  rfds, wfds;
    uint32_t voice_mask[] = { 0, 0, 0, 0 };
    snd_pcm_voice_conversion_t voice_conversion;
    int     voice_override = 0;
    int     num_frags = -1;
    char input_file[PATH_MAX];
    char cwd[PATH_MAX];
    screen_context_t screen_cxt;
    screen_window_t screen_win;
    screen_buffer_t screen_buf;
    int screen_fill_attribs[] = { SCREEN_BLIT_COLOR, COLOR_PURPLE, SCREEN_BLIT_END };
    int screen_dirty[4] = { 0, 0, 1024, 600 }; //start with sane default values

    int idle_mode = SCREEN_IDLE_MODE_KEEP_AWAKE;
    int usage = SCREEN_USAGE_NATIVE;

    if (screen_create_context(&screen_cxt, 0) != 0)
    {
    	return err("failed to create context");
    }

    if (screen_create_window(&screen_win, screen_cxt) != 0)
    {
    	err("failed to create window");
    	goto fail1;
    }

    if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage) != 0)
    {
    	err("failed to set native usage mode");
    	goto fail2;
    }

    if (screen_create_window_buffers(screen_win, 1) != 0)
    {
    	err("failed to set native usage mode");
    	goto fail2;
    }

    if(screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf) != 0)
    {
    	err("failed to get screen buffer");
    	goto fail2;
    }

    if (screen_fill(screen_cxt, screen_buf, screen_fill_attribs) != 0) {
    	err("failed to fill the screen");
    	goto fail3;
    }

    if (screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, screen_dirty+2) != 0) {
    	err("failed to get window size");
    	goto fail3;
    }

    if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_IDLE_MODE, &idle_mode) != 0)
    {
    	err("failed to set idle mode");
    	goto fail3;
    }

    if (screen_post_window(screen_win, screen_buf, 1, screen_dirty, 0) != 0) {
    	err("failed to post the window");
    	goto fail3;
    }

    if ((rtn = snd_pcm_open_preferred (&pcm_handle, &card, &dev, SND_PCM_OPEN_PLAYBACK)) < 0)
    {
        err ("device open");
        goto fail3;
    }

    getcwd(cwd, PATH_MAX);
    rtn = snprintf(input_file, PATH_MAX, "%s%s", cwd, WAV_RELATIVE_PATH);
    if (rtn > PATH_MAX - 1)
    {
    	err ("File name and path too long");
    	goto fail4;
    }

    if ((file = fopen (input_file, "r")) == 0)
    {
    	err ("File open failed");
    	goto fail4;
    }

    if (check_hdr (file) == -1) {
        err ("check_hdr failed");
        goto fail5;
    }

    samples = find_tag (file, "fmt ");
    fread (&wav_header, sizeof (wav_header), 1, file);
    fseek (file, (samples - sizeof (wave_hdr)), SEEK_CUR);

    sample_rate = ENDIAN_LE32 (wav_header.samples_per_sec);
    sample_channels = ENDIAN_LE16 (wav_header.channels);
    sample_bits = ENDIAN_LE16 (wav_header.bits_per_sample);

    printf ("SampleRate = %d, channels = %d, SampleBits = %d\n", sample_rate, sample_channels,
        sample_bits);

    /* disabling mmap is not actually required in this example but it is included to
     * demonstrate how it is used when it is required.
     */
    if ((rtn = snd_pcm_plugin_set_disable (pcm_handle, PLUGIN_DISABLE_MMAP)) < 0)
    {
        fprintf (stderr, "snd_pcm_plugin_set_disable failed: %s\n", snd_strerror (rtn));
        goto fail5;
    }

    memset (&pi, 0, sizeof (pi));
    pi.channel = SND_PCM_CHANNEL_PLAYBACK;
    if ((rtn = snd_pcm_plugin_info (pcm_handle, &pi)) < 0)
    {
        fprintf (stderr, "snd_pcm_plugin_info failed: %s\n", snd_strerror (rtn));
        goto fail5;
    }

    memset (&pp, 0, sizeof (pp));

    pp.mode = SND_PCM_MODE_BLOCK;
    pp.channel = SND_PCM_CHANNEL_PLAYBACK;
    pp.start_mode = SND_PCM_START_FULL;
    pp.stop_mode = SND_PCM_STOP_STOP;
    pp.buf.block.frag_size = pi.max_fragment_size;

    if (fragsize != -1)
    {
        pp.buf.block.frag_size = fragsize;
    }
    pp.buf.block.frags_max = num_frags;
    pp.buf.block.frags_min = 1;

    pp.format.interleave = 1;
    pp.format.rate = sample_rate;
    pp.format.voices = sample_channels;

    if (ENDIAN_LE16 (wav_header.format_tag) == 6)
        pp.format.format = SND_PCM_SFMT_A_LAW;
    else if (ENDIAN_LE16 (wav_header.format_tag) == 7)
        pp.format.format = SND_PCM_SFMT_MU_LAW;
    else if (sample_bits == 8)
        pp.format.format = SND_PCM_SFMT_U8;
    else if (sample_bits == 24)
        pp.format.format = SND_PCM_SFMT_S24;
    else
        pp.format.format = SND_PCM_SFMT_S16_LE;

    strcpy (pp.sw_mixer_subchn_name, "Wave playback channel");
    if ((rtn = snd_pcm_plugin_params (pcm_handle, &pp)) < 0)
    {
        fprintf (stderr, "snd_pcm_plugin_params failed: %s\n", snd_strerror (rtn));
        goto fail5;
    }

    if ((rtn = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) {
        fprintf (stderr, "snd_pcm_plugin_prepare failed: %s\n", snd_strerror (rtn));
        goto fail5;
    }

    if (voice_override)
    {
        snd_pcm_plugin_get_voice_conversion (pcm_handle, SND_PCM_CHANNEL_PLAYBACK,
            &voice_conversion);
        voice_conversion.matrix[0] = voice_mask[0];
        voice_conversion.matrix[1] = voice_mask[1];
        voice_conversion.matrix[2] = voice_mask[2];
        voice_conversion.matrix[3] = voice_mask[3];
        snd_pcm_plugin_set_voice_conversion (pcm_handle, SND_PCM_CHANNEL_PLAYBACK,
            &voice_conversion);
    }

    memset (&setup, 0, sizeof (setup));
    memset (&group, 0, sizeof (group));
    setup.channel = SND_PCM_CHANNEL_PLAYBACK;
    setup.mixer_gid = &group.gid;

    if ((rtn = snd_pcm_plugin_setup (pcm_handle, &setup)) < 0)
    {
        fprintf (stderr, "snd_pcm_plugin_setup failed: %s\n", snd_strerror (rtn));
        goto fail5;
    }

    printf ("Format %s \n", snd_pcm_get_format_name (setup.format.format));
    printf ("Frag Size %d \n", setup.buf.block.frag_size);
    printf ("Total Frags %d \n", setup.buf.block.frags);
    printf ("Rate %d \n", setup.format.rate);
    printf ("Voices %d \n", setup.format.voices);
    bsize = setup.buf.block.frag_size;

    if (group.gid.name[0] == 0)
    {
        fprintf (stderr, "Mixer Pcm Group [%s] Not Set \n", group.gid.name);
        goto fail5;
    }

    printf ("Mixer Pcm Group [%s]\n", group.gid.name);
    if ((rtn = snd_mixer_open (&mixer_handle, card, setup.mixer_device)) < 0)
    {
        fprintf (stderr, "snd_mixer_open failed: %s\n", snd_strerror (rtn));
        goto fail5;
    }

    samples = find_tag (file, "data");
    sample_buffer = malloc (bsize);
    FD_ZERO (&rfds);
    FD_ZERO (&wfds);
    bytes_read = 1;
    while (total_written < samples && bytes_read > 0)
    {
        if (tcgetpgrp (0) == getpid ())
            FD_SET (STDIN_FILENO, &rfds);
        FD_SET (snd_mixer_file_descriptor (mixer_handle), &rfds);
        FD_SET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds);

        rtn = max (snd_mixer_file_descriptor (mixer_handle),
            snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK));

        if (select (rtn + 1, &rfds, &wfds, NULL, NULL) == -1)
        {
        	err ("select");
        	goto fail6;
        }

        if (FD_ISSET (snd_pcm_file_descriptor (pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds))
        {
            snd_pcm_channel_status_t status;
            int     written = 0;

            if ((bytes_read = fread (sample_buffer, 1, min (samples - total_written, bsize), file)) <= 0)
                continue;
            written = snd_pcm_plugin_write (pcm_handle, sample_buffer, bytes_read);
            if (verbose)
                printf ("bytes written = %d \n", written);

            if (written < bytes_read)
            {
                memset (&status, 0, sizeof (status));
                status.channel = SND_PCM_CHANNEL_PLAYBACK;
                if (snd_pcm_plugin_status (pcm_handle, &status) < 0)
                {
                    fprintf (stderr, "underrun: playback channel status error\n");
                    goto fail6;
                }

                if (status.status == SND_PCM_STATUS_READY ||
                    status.status == SND_PCM_STATUS_UNDERRUN)
                {
                    if (snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK) < 0)
                    {
                        fprintf (stderr, "underrun: playback channel prepare error\n");
                        goto fail6;
                    }
                }
                if (written < 0)
                    written = 0;
                written += snd_pcm_plugin_write (pcm_handle, sample_buffer + written, bytes_read - written);
            }
            total_written += written;
        }
    }

    bytes_read = snd_pcm_plugin_flush (pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
    final_return_code = 0;

fail6:
    rtn = snd_mixer_close (mixer_handle);
fail5:
    fclose (file);
fail4:
    rtn = snd_pcm_close (pcm_handle);
fail3:
    screen_destroy_buffer(screen_buf);
fail2:
    screen_destroy_window(screen_win);
fail1:
    screen_destroy_context(screen_cxt);
    return final_return_code;
}
Esempio n. 20
0
static void NTO_PlayAudio(_THIS)
{
    int written, rval;
    int towrite;

#ifdef DEBUG_AUDIO
		fprintf(stderr, "NTO_PlayAudio\n");
#endif

	if( !this->enabled)
	   return;

	towrite = pcm_len;
	

    /* Write the audio data, checking for EAGAIN (buffer full) and underrun */
    do {
		written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite);
#ifdef DEBUG_AUDIO
		fprintf(stderr, "NTO_PlayAudio: written = %d towrite = %d\n",written,towrite);
#endif
		if (written != towrite)
		{
	        if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
			{
            	SDL_Delay(1);   /* Let a little CPU time go by and try to write again */
#ifdef DEBUG_AUDIO
				fprintf(stderr, "errno == EAGAIN written %d\n", written);
				towrite -= written; //we wrote some data
#endif
				continue;
        	}		
			else if((errno == EINVAL) || (errno == EIO))
			{
#ifdef DEBUG_AUDIO
					if(errno == EIO)
						fprintf(stderr,"snd_pcm_plugin_write failed EIO: %s\n", snd_strerror(written));	
					if(errno == EINVAL)
						fprintf(stderr,"snd_pcm_plugin_write failed EINVAL: %s\n", snd_strerror(written));	
								
#endif			
			
				  memset(&cstatus, 0, sizeof(cstatus));			
		         if( (rval = snd_pcm_plugin_status(audio_handle, &cstatus)) < 0 )
        		 {
#ifdef DEBUG_AUDIO
					fprintf(stderr, "snd_pcm_plugin_status failed %s\n",snd_strerror(rval));
#endif
		            SDL_SetError("snd_pcm_plugin_status failed: %s\n", snd_strerror(rval));
        		   return;
		        }	
		        
				if ( (cstatus.status == SND_PCM_STATUS_UNDERRUN) ||
					(cstatus.status == SND_PCM_STATUS_READY) )
				{
#ifdef DEBUG_AUDIO
					fprintf(stderr, "buffer underrun\n");
#endif
					if ( (rval = snd_pcm_plugin_prepare (audio_handle,SND_PCM_CHANNEL_PLAYBACK)) < 0 )
					{
#ifdef DEBUG_AUDIO
						fprintf(stderr, "NTO_PlayAudio: prepare failed %s\n",snd_strerror(rval));
#endif
						SDL_SetError("snd_pcm_plugin_prepare failed: %s\n",snd_strerror(rval) );
						return;
					}
					
				}		        		
 				continue;
			}
			else
			{
#ifdef DEBUG_AUDIO
						fprintf(stderr, "NTO_PlayAudio: snd_pcm_plugin_write failed unknown errno %d %s\n",errno, snd_strerror(rval));
#endif
				return;
			
			}
			
		}
		else
		{
			towrite -= written; //we wrote all remaining data
		}
    } while ( (towrite > 0)  && (this->enabled) );

    /* If we couldn't write, assume fatal error for now */
    if ( towrite != 0 ) {
        this->enabled = 0;
    }
	return;
}
Esempio n. 21
0
/*****************************************************************************
 * QNXaoutThread: asynchronous thread used to DMA the data to the device
 *****************************************************************************/
static void* QNXaoutThread( vlc_object_t *p_this )
{
    aout_instance_t * p_aout = (aout_instance_t*)p_this;
    struct aout_sys_t * p_sys = p_aout->output.p_sys;
    int canc = vlc_savecancel ();

    while ( vlc_object_alive (p_aout) )
    {
        aout_buffer_t * p_buffer;
        int i_tmp, i_size;
        uint8_t * p_bytes;

        if ( p_aout->output.output.i_format != VLC_CODEC_SPDIFL )
        {
            mtime_t next_date = 0;

            /* Get the presentation date of the next write() operation. It
             * is equal to the current date + duration of buffered samples.
             * Order is important here, since GetBufInfo is believed to take
             * more time than mdate(). */
            next_date = (mtime_t)GetBufInfo( p_aout ) * 1000000
                      / p_aout->output.output.i_bytes_per_frame
                      / p_aout->output.output.i_rate
                      * p_aout->output.output.i_frame_length;
            next_date += mdate();

            p_buffer = aout_OutputNextBuffer( p_aout, next_date, false );
        }
        else
        {
            p_buffer = aout_OutputNextBuffer( p_aout, 0, true );
        }

        if ( p_buffer != NULL )
        {
            p_bytes = p_buffer->p_buffer;
            i_size = p_buffer->i_nb_bytes;
        }
        else
        {
            i_size = DEFAULT_FRAME_SIZE / p_aout->output.output.i_frame_length
                      * p_aout->output.output.i_bytes_per_frame;
            p_bytes = p_aout->output.p_sys->p_silent_buffer;
            memset( p_bytes, 0, i_size );
        }

        i_tmp = snd_pcm_plugin_write( p_aout->output.p_sys->p_pcm_handle,
                                        (void *) p_bytes,
                                        (size_t) i_size );

        if( i_tmp < 0 )
        {
            msg_Err( p_aout, "write failed (%m)" );
        }

        if ( p_buffer != NULL )
        {
            aout_BufferFree( p_buffer );
        }
    }

    vlc_restorecancel (canc);
    return NULL;
}
Esempio n. 22
0
/*****************************************************************************
 * QNXaoutThread: asynchronous thread used to DMA the data to the device
 *****************************************************************************/
static int QNXaoutThread( aout_instance_t * p_aout )
{
    struct aout_sys_t * p_sys = p_aout->output.p_sys;

    while ( !p_aout->b_die )
    {
        aout_buffer_t * p_buffer;
        int i_tmp, i_size;
        byte_t * p_bytes;

        if ( p_aout->output.output.i_format != VLC_FOURCC('s','p','d','i') )
        {
            mtime_t next_date = 0;

            /* Get the presentation date of the next write() operation. It
             * is equal to the current date + duration of buffered samples.
             * Order is important here, since GetBufInfo is believed to take
             * more time than mdate(). */
            next_date = (mtime_t)GetBufInfo( p_aout ) * 1000000
                      / p_aout->output.output.i_bytes_per_frame
                      / p_aout->output.output.i_rate
                      * p_aout->output.output.i_frame_length;
            next_date += mdate();

            p_buffer = aout_OutputNextBuffer( p_aout, next_date, VLC_FALSE );
        }
        else
        {
            p_buffer = aout_OutputNextBuffer( p_aout, 0, VLC_TRUE );
        }

        if ( p_buffer != NULL )
        {
            p_bytes = p_buffer->p_buffer;
            i_size = p_buffer->i_nb_bytes;
        }
        else
        {
            i_size = DEFAULT_FRAME_SIZE / p_aout->output.output.i_frame_length
                      * p_aout->output.output.i_bytes_per_frame;
            p_bytes = p_aout->output.p_sys->p_silent_buffer;
            memset( p_bytes, 0, i_size );
        }

        i_tmp = snd_pcm_plugin_write( p_aout->output.p_sys->p_pcm_handle,
                                        (void *) p_bytes,
                                        (size_t) i_size );

        if( i_tmp < 0 )
        {
            msg_Err( p_aout, "write failed (%s)", strerror(errno) );
        }

        if ( p_buffer != NULL )
        {
            aout_BufferFree( p_buffer );
        }
    }

    return 0;
}
static void *processTones(void *dummy)
{
    bool done;
    int error;
    int length;
    int index;
    Tone *tone, *nextTone;
    snd_pcm_channel_status_t status;


    //pthread_setname_np(pthread_self(), "tonegen");

    // Main loop. Wait for audio driver to need more data
    while( live ) {
        pthread_mutex_lock( &toneMutex );
        if( tone_count == 0 ) {
            // Wait for a tone command to come in
            snd_pcm_playback_flush( playback_handle );
            snd_pcm_plugin_prepare( playback_handle, SND_PCM_CHANNEL_PLAYBACK );

            pthread_cond_wait( &condvar_newtone, &toneMutex );
        }
        if( tone_count == 0 ) {
            pthread_mutex_unlock( &toneMutex );
            continue;
        }
        pthread_mutex_unlock( &toneMutex );

        // Send tone data
        FD_ZERO( &write_handles );
        FD_SET( sample_handle, &write_handles );
        error = select(sample_handle + 1, NULL, &write_handles, NULL, NULL);

        if( error < 0 ) {
            // Select failed.
            slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "processTones select failed %d (%d)\n", error, errno);
            pthread_mutex_unlock( &toneMutex );
            live = DEAD;
            break;
        }

        length = 0;

        // This should always be true
        if( FD_ISSET( sample_handle, &write_handles ) ) {
        	int active_count = 0;
        	for(tone = tones; tone != NULL; tone = tone->next) {
                done = tone->killed || (tonepos > tone->end);
    			//fprintf (stderr,"processTone::writeTone (before active check) tone %ld tone->end %ld active %d done %d tonepos %ld \n", tone, tone->end, tone->active, done, tonepos);
                if( !done ) {
                    // Write the tone
                    error = writeTone(tone, (tone != tones));
                    //error = tone->generator(tone->position, length, sample_frequency, frag_buffer, &tone->data, terminating);
                    if( error != EOK ) {
                        done = true;
                    }
                    active_count++;
                }

                tone->active &= !done;
    			//fprintf (stderr,"processTone::writeTone tone %ld tone->end %ld active %d tonepos %ld \n", tone, tone->end, tone->active, tonepos);
        	}

        	for(index = 0; index < frag_samples; index++) {
        		record_buffer[index*2  ] = stage_buffer[index] / stage_samples[index];
        		record_buffer[index*2+1] = stage_buffer[index] / stage_samples[index];
        	}

        	pthread_mutex_lock(&fillMutex);

        	if (render_buffer != NULL) {
        		memcpy(render_buffer, record_buffer, frame_size);
        	}

        	pthread_mutex_unlock(&fillMutex);

			tonepos += frag_samples;

			if (active_count > 0) {
				fprintf (stderr,"processTone tonepos %ld \n", tonepos);

				error = snd_pcm_plugin_write (playback_handle, record_buffer, frame_size);
				if( error != frame_size ) {
				   memset (&status, 0, sizeof (status));
					status.channel = SND_PCM_CHANNEL_PLAYBACK;
					if ((error = snd_pcm_plugin_status (playback_handle, &status)) < 0)
					{
						slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "retrieving audio interface status failed (%s)\n", snd_strerror (error));
					} else if (status.status == SND_PCM_STATUS_READY ||
							   status.status == SND_PCM_STATUS_UNDERRUN ||
							   status.status == SND_PCM_STATUS_CHANGE)
					{
						if ((error = snd_pcm_plugin_prepare (playback_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) {
							slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "cannot prepare audio interface for use (%s)\n", snd_strerror (error));
						}
					} else {
						slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "non-underrun write failure (%s)\n", snd_strerror (error));
					}
					// Retry now that we're prepared
					error = snd_pcm_plugin_write (playback_handle, record_buffer, frame_size);
				}
				if( error != frame_size ) {
					slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "write to audio interface failed (%s) %d\n", snd_strerror (error), error);
				}
			}

        } else {
            slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unknown file handle activated" );
        }

		pthread_mutex_lock( &toneMutex );


		//fprintf (stderr,"processTone::delete tones %lx count %d \n", tones, tone_count);

        int delete_count;
        do {
        	delete_count = 0;
			for(tone = tones; tone != NULL; tone = tone->next) {
				done = tone->killed || (tonepos > tone->end);
				if( done || !tone->active ) {
					// Remove the tone from the list
					if (tone->prev != NULL) {
						tone->prev->next = tone->next;
					} else {
						tones = tone->next;
					}
					if (tone->next != NULL) {
						tone->next->prev = tone->prev;
					}

					tone_count--;

					free(tone);

					delete_count++;

					fprintf (stderr,"processTone::delete tone %lx tones %lx count %d \n", tone, tones, tone_count);

					break;
				}
			}
        } while (delete_count > 0);

		pthread_mutex_unlock( &toneMutex );

        if (tone_count == 0) {
        	memset(record_buffer, 0, frame_size);
        }
    }

    return NULL;
}