Beispiel #1
0
static void
rdpsnd_queue_complete_pending(void)
{
	struct timeval now;
	long elapsed;
	struct audio_packet *packet;

	gettimeofday(&now, NULL);

	while (queue_pending != queue_lo)
	{
		packet = &packet_queue[queue_pending];

		if (now.tv_sec < packet->completion_tv.tv_sec)
			break;

		if ((now.tv_sec == packet->completion_tv.tv_sec) &&
		    (now.tv_usec < packet->completion_tv.tv_usec))
			break;

		elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
			(packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
		elapsed /= 1000;

		xfree(packet->s.data);
		rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
		queue_pending = (queue_pending + 1) % MAX_QUEUE;
	}
}
Beispiel #2
0
void
wave_out_close(void)
{
	/* Ack all remaining packets */
	while (queue_lo != queue_hi)
	{
		rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index);
		free(packet_queue[queue_lo].s.data);
		queue_lo = (queue_lo + 1) % MAX_QUEUE;
	}

	if (o_device != NULL)
		ao_close(o_device);

	ao_shutdown();
}
Beispiel #3
0
void
wave_out_close(void)
{
	/* Ack all remaining packets */
	while (queue_lo != queue_hi)
	{
		rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index);
		free(packet_queue[queue_lo].s.data);
		queue_lo = (queue_lo + 1) % MAX_QUEUE;
	}

#if defined I_FLUSH && defined FLUSHW
	/* Flush the audiobuffer */
	ioctl(This->dsp_, I_FLUSH, FLUSHW);
#endif
#if defined AUDIO_FLUSH
	ioctl(This->dsp_, AUDIO_FLUSH, NULL);
#endif
	close(This->dsp_);
}
Beispiel #4
0
void
wave_out_close(void)
{
	/* Ack all remaining packets */
#if (defined(IRIX_DEBUG))
	fprintf(stderr, "wave_out_close: begin\n");
#endif

	while (queue_lo != queue_hi)
	{
		rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index);
		free(packet_queue[queue_lo].s.data);
		queue_lo = (queue_lo + 1) % MAX_QUEUE;
	}
	alDiscardFrames(output_port, 0);

	alClosePort(output_port);
	alFreeConfig(audioconfig);
#if (defined(IRIX_DEBUG))
	fprintf(stderr, "wave_out_close: returning\n");
#endif
}
Beispiel #5
0
void
wave_out_play(void)
{
	struct audio_packet *packet;
	ssize_t len;
	STREAM out;
	static long startedat_us;
	static long startedat_s;
	static BOOL started = False;
	struct timeval tv;
	audio_buf_info info;

	while (1)
	{
		if (queue_lo == queue_hi)
		{
			g_dsp_busy = 0;
			return;
		}

		packet = &packet_queue[queue_lo];
		out = &packet->s;

		if (!started)
		{
			gettimeofday(&tv, NULL);
			startedat_us = tv.tv_usec;
			startedat_s = tv.tv_sec;
			started = True;
		}

		len = out->end - out->p;

		if (!g_driver_broken)
		{
			memset(&info, 0, sizeof(info));
			if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
			{
				perror("SNDCTL_DSP_GETOSPACE");
				return;
			}

			if (info.fragments == 0)
			{
				g_dsp_busy = 1;
				return;
			}

			if (info.fragments * info.fragsize < len
			    && info.fragments * info.fragsize > 0)
			{
				len = info.fragments * info.fragsize;
			}
		}


		len = write(g_dsp_fd, out->p, len);
		if (len == -1)
		{
			if (errno != EWOULDBLOCK)
				perror("write audio");
			g_dsp_busy = 1;
			return;
		}

		out->p += len;
		if (out->p == out->end)
		{
			long long duration;
			long elapsed;

			gettimeofday(&tv, NULL);
			duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate)));
			elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);

			if (elapsed >= (duration * 85) / 100)
			{
				rdpsnd_send_completion(packet->tick, packet->index);
				free(out->data);
				queue_lo = (queue_lo + 1) % MAX_QUEUE;
				started = False;
			}
			else
			{
				g_dsp_busy = 1;
				return;
			}
		}
	}
}
Beispiel #6
0
void
wave_out_play(void)
{
	struct audio_packet *packet;
	STREAM out;
	char outbuf[WAVEOUTBUF];
	int offset, len, i;
	static long prev_s, prev_us;
	unsigned int duration;
	struct timeval tv;
	int next_tick;

	if (g_reopened)
	{
		g_reopened = False;
		gettimeofday(&tv, NULL);
		prev_s = tv.tv_sec;
		prev_us = tv.tv_usec;
	}

	if (queue_lo == queue_hi)
	{
		g_dsp_busy = 0;
		return;
	}

	packet = &packet_queue[queue_lo];
	out = &packet->s;

	if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
	{
		next_tick = packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
	}
	else
	{
		next_tick = (packet->tick + 65535) % 65536;
	}

	len = 0;

	if (g_samplerate == 22050)
	{
		/* Resample to 44100 */
		for (i = 0; (i < ((WAVEOUTBUF / 4) * (3 - g_samplewidth))) && (out->p < out->end);
		     i++)
		{
			/* On a stereo-channel we must make sure that left and right
			   does not get mixed up, so we need to expand the sample-
			   data with channels in mind: 1234 -> 12123434
			   If we have a mono-channel, we can expand the data by simply
			   doubling the sample-data: 1234 -> 11223344 */
			if (g_channels == 2)
				offset = ((i * 2) - (i & 1)) * g_samplewidth;
			else
				offset = (i * 2) * g_samplewidth;

			memcpy(&outbuf[offset], out->p, g_samplewidth);
			memcpy(&outbuf[g_channels * g_samplewidth + offset], out->p, g_samplewidth);

			out->p += g_samplewidth;
			len += 2 * g_samplewidth;
		}
	}
	else
	{
		len = (WAVEOUTBUF > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTBUF;
		memcpy(outbuf, out->p, len);
		out->p += len;
	}

	ao_play(o_device, outbuf, len);

	gettimeofday(&tv, NULL);

	duration = ((tv.tv_sec - prev_s) * 1000000 + (tv.tv_usec - prev_us)) / 1000;

	if (packet->tick > next_tick)
		next_tick += 65536;

	if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
	{
		prev_s = tv.tv_sec;
		prev_us = tv.tv_usec;

		if (abs((next_tick - packet->tick) - duration) > 20)
		{
			DEBUG(("duration: %d, calc: %d, ", duration, next_tick - packet->tick));
			DEBUG(("last: %d, is: %d, should: %d\n", packet->tick,
			       (packet->tick + duration) % 65536, next_tick % 65536));
		}

		/* Until all drivers are using the windows sound-ticks, we need to
		   substract the 50 ticks added later by rdpsnd.c */
		rdpsnd_send_completion(((packet->tick + duration) % 65536) - 50, packet->index);
		free(out->data);
		queue_lo = (queue_lo + 1) % MAX_QUEUE;
	}

	g_dsp_busy = 1;
	return;
}
Beispiel #7
0
void
wave_out_play(void)
{
	struct audio_packet *packet;
	ssize_t len;
	unsigned int i;
	uint8 swap;
	STREAM out;
	static BOOL swapped = False;
	int gf;

	while (1)
	{
		if (queue_lo == queue_hi)
		{
			This->dsp_bu = False;
			return;
		}

		packet = &packet_queue[queue_lo];
		out = &packet->s;

		/* Swap the current packet, but only once */
		if (g_swapaudio && !swapped)
		{
			for (i = 0; i < out->end - out->p; i += 2)
			{
				swap = *(out->p + i);
				*(out->p + i) = *(out->p + i + 1);
				*(out->p + i + 1) = swap;
			}
			swapped = True;
		}

		len = out->end - out->p;

		alWriteFrames(output_port, out->p, len / combinedFrameSize);

		out->p += len;
		if (out->p == out->end)
		{
			gf = alGetFilled(output_port);
			if (gf < (4 * maxFillable / 10))
			{
				rdpsnd_send_completion(packet->tick, packet->index);
				free(out->data);
				queue_lo = (queue_lo + 1) % MAX_QUEUE;
				swapped = False;
			}
			else
			{
#if (defined(IRIX_DEBUG))
/*  				fprintf(stderr,"Busy playing...\n"); */
#endif
				This->dsp_bu = True;
				usleep(10);
				return;
			}
		}
	}
}
Beispiel #8
0
static void
rdpsnd_process_packet(uint8 opcode, STREAM s)
{
	uint16 vol_left, vol_right;
	static uint16 tick, format;
	static uint8 packet_index;

	switch (opcode)
	{
		case RDPSND_WRITE:
			in_uint16_le(s, tick);
			in_uint16_le(s, format);
			in_uint8(s, packet_index);
			in_uint8s(s, 3);
			DEBUG_SOUND(("RDPSND: RDPSND_WRITE(tick: %u, format: %u, index: %u, data: %u bytes)\n", (unsigned) tick, (unsigned) format, (unsigned) packet_index, (unsigned) s->size - 8));

			if (format >= MAX_FORMATS)
			{
				error("RDPSND: Invalid format index\n");
				break;
			}

			if (!device_open || (format != current_format))
			{
				/*
				 * If we haven't selected a device by now, then either
				 * we've failed to find a working device, or the server
				 * is sending bogus RDPSND_WRITE.
				 */
				if (!current_driver)
				{
					rdpsnd_send_completion(tick, packet_index);
					break;
				}
				if (!device_open && !current_driver->wave_out_open())
				{
					rdpsnd_send_completion(tick, packet_index);
					break;
				}
				if (!current_driver->wave_out_set_format(&formats[format]))
				{
					rdpsnd_send_completion(tick, packet_index);
					current_driver->wave_out_close();
					device_open = False;
					break;
				}
				device_open = True;
				current_format = format;
			}

			rdpsnd_queue_write(rdpsnd_dsp_process
					   (s->p, s->end - s->p, current_driver,
					    &formats[current_format]), tick, packet_index);
			return;
			break;
		case RDPSND_CLOSE:
			DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n"));
			if (device_open)
				current_driver->wave_out_close();
			device_open = False;
			break;
		case RDPSND_NEGOTIATE:
			rdpsnd_process_negotiate(s);
			break;
		case RDPSND_PING:
			rdpsnd_process_ping(s);
			break;
		case RDPSND_SET_VOLUME:
			in_uint16_le(s, vol_left);
			in_uint16_le(s, vol_right);
			DEBUG_SOUND(("RDPSND: RDPSND_VOLUME(left: 0x%04x (%u %%), right: 0x%04x (%u %%))\n", (unsigned) vol_left, (unsigned) vol_left / 655, (unsigned) vol_right, (unsigned) vol_right / 655));
			if (device_open)
				current_driver->wave_out_volume(vol_left, vol_right);
			break;
		default:
			unimpl("RDPSND packet type %x\n", opcode);
			break;
	}
}
Beispiel #9
0
void
wave_out_play(void)
{
	struct audio_packet *packet;
	audio_info_t info;
	ssize_t len;
	unsigned int i;
	uint8 swap;
	STREAM out;
	static BOOL swapped = False;
	static BOOL sentcompletion = True;
	static uint32 samplecnt = 0;
	static uint32 numsamples;

	while (1)
	{
		if (g_reopened)
		{
			/* Device was just (re)openend */
			samplecnt = 0;
			swapped = False;
			sentcompletion = True;
			g_reopened = False;
		}

		if (queue_lo == queue_hi)
		{
			This->dsp_bu = 0;
			return;
		}

		packet = &packet_queue[queue_lo];
		out = &packet->s;

		/* Swap the current packet, but only once */
		if (g_swapaudio && !swapped)
		{
			for (i = 0; i < out->end - out->p; i += 2)
			{
				swap = *(out->p + i);
				*(out->p + i) = *(out->p + i + 1);
				*(out->p + i + 1) = swap;
			}
			swapped = True;
		}

		if (sentcompletion)
		{
			sentcompletion = False;
			numsamples = (out->end - out->p) / g_samplewidth;
		}

		len = 0;

		if (out->end != out->p)
		{
			len = write(This->dsp_, out->p, out->end - out->p);
			if (len == -1)
			{
				if (errno != EWOULDBLOCK)
					perror("write audio");
				This->dsp_bu = 1;
				return;
			}
		}

		out->p += len;
		if (out->p == out->end)
		{
			if (ioctl(This->dsp_, AUDIO_GETINFO, &info) == -1)
			{
				perror("AUDIO_GETINFO");
				return;
			}

			/* Ack the packet, if we have played at least 70% */
			if (info.play.samples >= samplecnt + ((numsamples * 7) / 10))
			{
				samplecnt += numsamples;
				rdpsnd_send_completion(packet->tick, packet->index);
				free(out->data);
				queue_lo = (queue_lo + 1) % MAX_QUEUE;
				swapped = False;
				sentcompletion = True;
			}
			else
			{
				This->dsp_bu = 1;
				return;
			}
		}
	}
}
Beispiel #10
0
void
rdpsnd_process(STREAM s)
{
	uint8 type;
	uint16 datalen;
	uint32 volume;
	static uint16 tick, format;
	static uint8 packet_index;
	static BOOL awaiting_data_packet;

#ifdef RDPSND_DEBUG
	printf("RDPSND recv:\n");
	hexdump(s->p, s->end - s->p);
#endif

	if (awaiting_data_packet)
	{
		if (format >= MAX_FORMATS)
		{
			error("RDPSND: Invalid format index\n");
			return;
		}

		if (!device_open || (format != current_format))
		{
			if (!device_open && !wave_out_open())
			{
				rdpsnd_send_completion(tick, packet_index);
				return;
			}
			if (!wave_out_set_format(&formats[format]))
			{
				rdpsnd_send_completion(tick, packet_index);
				wave_out_close();
				device_open = False;
				return;
			}
			device_open = True;
			current_format = format;
		}

		wave_out_write(s, tick, packet_index);
		awaiting_data_packet = False;
		return;
	}

	in_uint8(s, type);
	in_uint8s(s, 1);	/* unknown? */
	in_uint16_le(s, datalen);

	switch (type)
	{
		case RDPSND_WRITE:
			in_uint16_le(s, tick);
			in_uint16_le(s, format);
			in_uint8(s, packet_index);
			awaiting_data_packet = True;
			break;
		case RDPSND_CLOSE:
			wave_out_close();
			device_open = False;
			break;
		case RDPSND_NEGOTIATE:
			rdpsnd_process_negotiate(s);
			break;
		case RDPSND_UNKNOWN6:
			rdpsnd_process_unknown6(s);
			break;
		case RDPSND_SET_VOLUME:
			in_uint32(s, volume);
			if (device_open)
			{
				wave_out_volume((volume & 0xffff), (volume & 0xffff0000) >> 16);
			}
			break;
		default:
			unimpl("RDPSND packet type %d\n", type);
			break;
	}
}