Example #1
0
static gboolean
gst_nas_sink_unprepare (GstAudioSink * asink)
{
    GstNasSink *sink = GST_NAS_SINK (asink);

    if (sink->flow != AuNone) {
        AuBool clocked;
        int num_elements;
        AuStatus status;
        AuElement *oldelems;

        GST_DEBUG_OBJECT (sink, "flushing buffer");
        NAS_flush (sink);

        oldelems =
            AuGetElements (sink->audio, sink->flow, &clocked, &num_elements,
                           &status);
        if (num_elements > 0) {
            GST_DEBUG_OBJECT (sink, "GetElements status: %i", status);
            if (oldelems)
                AuFreeElements (sink->audio, num_elements, oldelems);
        }

        AuStopFlow (sink->audio, sink->flow, NULL);
        AuReleaseScratchFlow (sink->audio, sink->flow, NULL);
        sink->flow = AuNone;
    }
    sink->need_data = 0;

    return TRUE;
}
Example #2
0
int ao_plugin_close(ao_device *device)
{
    ao_nas_internal *internal = (ao_nas_internal *) device->internal;

    if(internal->aud) {
        AuStopFlow(internal->aud, internal->flow, 0);
        AuCloseServer(internal->aud);
    }
    return 1;
}
Example #3
0
static void
gst_nas_sink_reset (GstAudioSink * asink)
{
    GstNasSink *sink = GST_NAS_SINK (asink);

    GST_DEBUG_OBJECT (sink, "reset");

    if (sink->flow != AuNone)
        AuStopFlow (sink->audio, sink->flow, NULL);
}
Example #4
0
static int nas_close(WINE_WAVEOUT* wwo)
{
  AuEvent ev;

  nas_free(wwo);

  AuStopFlow(wwo->AuServ, wwo->AuFlow, NULL);
  AuDestroyFlow(wwo->AuServ, wwo->AuFlow, NULL);
  AuFlush(wwo->AuServ);
  AuNextEvent(wwo->AuServ, AuTrue, &ev);
  AuDispatchEvent(wwo->AuServ, &ev);

  wwo->AuFlow = 0;
  wwo->open = 0;
  wwo->BufferUsed = 0;
  wwo->freeBytes = 0;
  wwo->SoundBuffer = NULL;
  return 1;
}
Example #5
0
static AuBool
nas_event_handler(AuServer *aud, AuEvent *ev, AuEventHandlerRec *hnd)
{
	AuElementNotifyEvent *event = (AuElementNotifyEvent*)ev;
	audio_job_t aj = hnd->data;
	snsd_t *snsd = audio_job_device_data(aj);

	NAS_DEBUG_EV("event_handler(): "
		     "type %s kind %s state %s->%s reason %s "
		     "numbytes %u\n",
		     nas_event_type(event->type),
		     nas_elementnotify_kind(event->kind),
		     nas_state(event->prev_state),
		     nas_state(event->cur_state),
		     nas_reason(event->reason),
		     (uint32_t)event->num_bytes);

	if (event->num_bytes > INT_MAX) {
		NAS_CRITICAL("num_bytes > 2GB, server buggy?\n");
	}

	switch (event->reason) {
	case AuReasonWatermark:
		nas_read(aj, event->num_bytes);
		break;
	case AuReasonUnderrun:
		/* buffer underrun -> refill buffer */
		if (nas_read(aj, event->num_bytes) != 0) {
			event->cur_state = AuStateStart;
			NAS_DEBUG_EV("restarting\n");
			break;
		}
		NAS_DEBUG_S("Can't refill buffer, stopping flow.\n");
		AuStopFlow(aud, snsd->flow, NULL);
		aj->play_state = MTPSTATE_STOP;
		break;
	default:
		break;
	}

	return AuTrue;
}
Example #6
0
static gboolean
gst_nas_sink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
{
  GstNasSink *sink = GST_NAS_SINK (asink);

  /*spec->bytes_per_sample = sink->rate * NAS_SOUND_PORT_DURATION; */
  /*spec->bytes_per_sample = (spec->width / 8) * spec->channels; */
  memset (spec->silence_sample, 0, spec->bytes_per_sample);
  GST_DEBUG_OBJECT (sink, "Sample %d", spec->bytes_per_sample);

  if (sink->audio == NULL)
    return TRUE;

  if (sink->flow != AuNone) {
    GST_DEBUG_OBJECT (sink, "flushing buffer");
    NAS_flush (sink);
    AuStopFlow (sink->audio, sink->flow, NULL);
    AuReleaseScratchFlow (sink->audio, sink->flow, NULL);
    sink->flow = AuNone;
  }

  return NAS_createFlow (sink, spec);
}
Example #7
0
static gboolean
gst_nas_sink_close (GstAudioSink * asink)
{
  GstNasSink *sink = GST_NAS_SINK (asink);

  if (sink->audio == NULL)
    return TRUE;

  if (sink->flow != AuNone) {
    NAS_flush (sink);

    AuStopFlow (sink->audio, sink->flow, NULL);
    AuReleaseScratchFlow (sink->audio, sink->flow, NULL);
    sink->flow = AuNone;
  }

  sink->need_data = 0;

  AuCloseServer (sink->audio);
  sink->audio = NULL;

  GST_DEBUG_OBJECT (sink, "closed audio device");
  return TRUE;
}
Example #8
0
static AuBool
NAS_EventHandler (AuServer * aud, AuEvent * ev, AuEventHandlerRec * handler)
{
    GstNasSink *sink = (GstNasSink *) handler->data;
    AuElementNotifyEvent *notify;

    switch (ev->type) {

    case AuEventTypeElementNotify:

        notify = (AuElementNotifyEvent *) ev;

        switch (notify->kind) {

        case AuElementNotifyKindLowWater:
            NAS_sendData (sink, notify->num_bytes);
            break;

        case AuElementNotifyKindState:

            switch (notify->cur_state) {

            case AuStateStop:

                if (sink->flow != AuNone) {
                    if (notify->reason == AuReasonEOF)
                        AuStopFlow (handler->aud, sink->flow, NULL);
                    AuReleaseScratchFlow (handler->aud, sink->flow, NULL);
                    sink->flow = AuNone;
                }
                AuUnregisterEventHandler (handler->aud, handler);
                break;

            case AuStatePause:

                switch (notify->reason) {
                case AuReasonUnderrun:
                case AuReasonOverrun:
                case AuReasonEOF:
                case AuReasonWatermark:

                    NAS_sendData (sink, notify->num_bytes);

                    break;

                case AuReasonHardware:

                    if (AuSoundRestartHardwarePauses)
                        AuStartFlow (handler->aud, sink->flow, NULL);
                    else
                        AuStopFlow (handler->aud, sink->flow, NULL);

                    break;
                }
                break;
            }
            break;
        }
        break;
    }

    return AuTrue;
}
Example #9
0
static int
sound_nas_play(audio_job_t aj)
{
	/* stream stuff */
	Lisp_Media_Stream *ms;
	media_substream *mss;
	/* thread stuff */
	media_thread_play_state mtp;
	/* device stuff */
	Lisp_Object device;
	Lisp_Audio_Device *lad = NULL;
	sound_nas_data_t *snd = NULL;
	/* nas stuff */
	AuElement elms[3];
	AuStatus as;
	int bsize = 0;
	/* subthread stuff */
	sound_nas_aj_data_t _snsd, *snsd = &_snsd;
	sxe_mse_volume_args _volargs, *volargs = &_volargs;
	sxe_mse_rerate_args _rrargs, *rrargs = &_rrargs;
	/* cache stuff */
	int alloced_myself = 0;

	SOUND_UNPACK_MT(aj, device, ms, mss, lad, snd, snsd->mtap);

	/* refuse to do anything if the AuServer pointer is not set */
	if (snd->aud == NULL) {
		NAS_DEBUG_C("b0rked connection, gute Nacht!\n");
		return 0;
	}

	/* install error handlers before anything else */
	AuSetErrorHandler(snd->aud, nas_error_handler);
	AuSetIOErrorHandler(snd->aud, nas_IOerror_handler);

	/* find physical output device */
	snsd->dev = nas_find_device(snd->aud, snsd->mtap->channels);

	if (snsd->dev == AuNone ||
	    !(snsd->flow = AuCreateFlow(snd->aud, NULL))) {
		/* No physical output device found or flow creation failed. */
		NAS_DEBUG_C("no physical devices for this stream\n");
		return 0;
	}

	/* A system call interrupted with a SIGALRM or SIGIO
	   comes back here */
	if (SETJMP(nas_server_sig)) {
		NAS_CRITICAL("Caught the lethal signal.\n");
		snd->aud = NULL;
		sound_nas_finish(snd);
		goto uhoh;
	}

	/* init the snsd */
	snsd->samplerate = 0;
	snsd->framesize = (snsd->channels = snsd->mtap->channels)
		* sizeof(int16_t);
	snsd->msf = MEDIA_SAMPLE_FORMAT(sxe_msf_S16);
	snsd->coe_ch_cnt = 0;
	snsd->resolution =
		(snsd->mtap->samplerate * MTPSTATE_REACT_TIME) / 1000000;
	bsize = (snsd->resolution + NAS_FRAG_SIZE - 1) & ~(NAS_FRAG_SIZE-1);

	snsd->snd = snd;
	snsd->buffer_size = bsize;
	snsd->writepos = snsd->readpos = 0;
	snsd->overfill = snsd->underrun = 0;

	/* set up flow */
	AuMakeElementImportClient(elms+0, snsd->mtap->samplerate,
				  AuFormatLinearSigned16LSB,
				  snsd->mtap->channels,
				  AuTrue,
				  bsize, bsize / 2,
				  0, NULL);
	snsd->gain = AuFixedPointFromFraction(1, 1);
	AuMakeElementMultiplyConstant(elms+1, 0, snsd->gain);
	AuMakeElementExportDevice(elms+2, 0, snsd->dev,
				  snsd->mtap->samplerate,
				  AuUnlimitedSamples, 0, NULL);
	AuSetElements(snd->aud, snsd->flow, AuTrue, 3, elms, &as);

	if (as != AuSuccess) {
		NAS_DEBUG_C("play(): AuSetElements failed\n");
		return 0;
	}

#if 0				/* atm we insist on having stereo access */
	/* the channel effect */
	ADD_MEDIA_SAMPLE_EFFECT(
		snsd->coe_chain, snsd->coe_ch_cnt,
		MEDIA_SAMPLE_EFFECT(sxe_mse_2ch_to_1ch), NULL);
#endif

	/* the volume effect */
	ADD_MEDIA_SAMPLE_EFFECT(
		snsd->coe_chain, snsd->coe_ch_cnt,
		MEDIA_SAMPLE_EFFECT(sxe_mse_volume), volargs);
	volargs->num_channels = snsd->channels;
	snsd->volargs = volargs;

	/* the rerate effect */
	ADD_MEDIA_SAMPLE_EFFECT(
		snsd->coe_chain, snsd->coe_ch_cnt,
		MEDIA_SAMPLE_EFFECT(sxe_mse_rerate), rrargs);
	rrargs->num_channels = snsd->channels;
	rrargs->srcrate = rrargs->tgtrate = 1;
	snsd->rrargs = rrargs;

	AuRegisterEventHandler(snd->aud, AuEventHandlerIDMask |
			       AuEventHandlerTypeMask,
			       AuEventTypeElementNotify, snsd->flow,
			       nas_event_handler, (AuPointer)aj);

	/* rewind the stream */
	media_stream_meth(ms, rewind)(mss);

	/* play chunks of the stream */
	SXE_MUTEX_LOCK(&aj->mtx);
	if (aj->buffer_alloc_size < SOUND_MAX_AUDIO_FRAME_SIZE) {
		alloced_myself = 1;
		aj->buffer = xmalloc_atomic(SOUND_MAX_AUDIO_FRAME_SIZE);
		aj->buffer_alloc_size = SOUND_MAX_AUDIO_FRAME_SIZE;
	}
	SXE_MUTEX_UNLOCK(&aj->mtx);
	snsd->mtp = MTPSTATE_STOP;
	snsd->volume = -1;
	audio_job_device_data(aj) = snsd;

	/* prefill the buffer */
	NAS_DEBUG_S("prefill the buffer: %d\n", 4*bsize);
	if (!nas_fill(aj, 4*bsize))
		goto uhoh;

	while (aj->play_state != MTPSTATE_STOP) {

#if 0
		if (aj->volume != snsd->volume) {
			AuElementParameters aep;
			NAS_DEBUG_S("Setting volume.\n");
			snsd->volume = aj->volume;
			snsd->gain = AU_FIXED_POINT_SCALE*(snsd->volume)/127;
			aep.parameters[AuParmsMultiplyConstantConstant] =
				snsd->gain;
			aep.flow = snd->flow;
			aep.element_num = 1;
			aep.num_parameters = AuParmsMultiplyConstant;

			AuSetElementParameters(snd->aud, 1, &aep, &as);
			if (as != AuSuccess) {
				NAS_DEBUG_S("Setting volume failed.\n");
			}
		}
#endif

#ifdef EF_USE_ASYNEQ
		/* events for me audio-job? */
		if (audio_job_queue(aj)) {
			sound_nas_handle_aj_events(aj);
		}
#endif

		SXE_MUTEX_LOCK(&aj->mtx);
		mtp = aj->play_state;
		SXE_MUTEX_UNLOCK(&aj->mtx);
		switch (mtp) {
		case MTPSTATE_RUN:
			if (snsd->mtp != mtp) {
				NAS_DEBUG("ah, gotta work again\n");
				AuStartFlow(snd->aud, snsd->flow, &as);
				if (as != AuSuccess) {
					NAS_DEBUG_C("play(): "
						    "AuStartFlow failed\n");
					aj->play_state = MTPSTATE_STOP;
				}
			}
			nas_empty_event_queue(snsd);
			usleep(snsd->resolution);
			break;
		case MTPSTATE_PAUSE:
			if (snsd->mtp != mtp) {
				NAS_DEBUG("sleeping for %d\n",
					  snsd->resolution);
				AuStopFlow(snd->aud, snsd->flow, &as);
			}
			usleep(snsd->resolution);
			break;

		case MTPSTATE_UNKNOWN:
		case MTPSTATE_STOP:
		case NUMBER_OF_MEDIA_THREAD_PLAY_STATES:
		default:
			NAS_DEBUG("ACK, quit\n");
			AuStopFlow(snd->aud, snsd->flow, &as);
			SXE_MUTEX_LOCK(&aj->mtx);
			aj->play_state = MTPSTATE_STOP;
			SXE_MUTEX_UNLOCK(&aj->mtx);
			break;
		}
		snsd->mtp = mtp;
	}

uhoh:
	/* -- Close and shutdown -- */
	SXE_MUTEX_LOCK(&aj->mtx);
	if (alloced_myself && aj->buffer) {
		xfree(aj->buffer);
	}
	aj->buffer = NULL;
	aj->buffer_alloc_size = 0;
	SXE_MUTEX_UNLOCK(&aj->mtx);

	return 1;
}