⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rdpsnd.c

📁 LInux 下的远程桌面工具 Rdesktop
💻 C
📖 第 1 页 / 共 2 页
字号:
				{					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;		case RDPSND_REC_NEGOTIATE:			rdpsnd_process_rec_negotiate(s);			break;		case RDPSND_REC_START:			in_uint16_le(s, format);			DEBUG_SOUND(("RDPSND: RDPSND_REC_START(format: %u)\n", (unsigned) format));			if (format >= MAX_FORMATS)			{				error("RDPSND: Invalid format index\n");				break;			}			if (rec_device_open)			{				error("RDPSND: Multiple RDPSND_REC_START\n");				break;			}			if (!current_driver->wave_in_open())				break;			if (!current_driver->wave_in_set_format(&rec_formats[format]))			{				error("RDPSND: Device not accepting format\n");				current_driver->wave_in_close();				break;			}			rec_current_format = format;			rec_device_open = True;			break;		case RDPSND_REC_STOP:			DEBUG_SOUND(("RDPSND: RDPSND_REC_STOP()\n"));			rdpsnd_flush_record();			if (rec_device_open)				current_driver->wave_in_close();			rec_device_open = False;			break;		case RDPSND_REC_SET_VOLUME:			in_uint16_le(s, vol_left);			in_uint16_le(s, vol_right);			DEBUG_SOUND(("RDPSND: RDPSND_REC_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 (rec_device_open)				current_driver->wave_in_volume(vol_left, vol_right);			break;		default:			unimpl("RDPSND packet type %x\n", opcode);			break;	}}static voidrdpsnd_process(STREAM s){	uint16 len;	while (!s_check_end(s))	{		/* New packet */		if (packet.size == 0)		{			if ((s->end - s->p) < 4)			{				error("RDPSND: Split at packet header. Things will go south from here...\n");				return;			}			in_uint8(s, packet_opcode);			in_uint8s(s, 1);	/* Padding */			in_uint16_le(s, len);			DEBUG_SOUND(("RDPSND: == Opcode %x Length: %d ==\n",				     (int) packet_opcode, (int) len));			packet.p = packet.data;			packet.end = packet.data + len;			packet.size = len;		}		else		{			len = MIN(s->end - s->p, packet.end - packet.p);			/* Microsoft's server is so broken it's not even funny... */			if (packet_opcode == RDPSND_WRITE)			{				if ((packet.p - packet.data) < 12)					len = MIN(len, 12 - (packet.p - packet.data));				else if ((packet.p - packet.data) == 12)				{					DEBUG_SOUND(("RDPSND: Eating 4 bytes of %d bytes...\n",						     len));					in_uint8s(s, 4);					len -= 4;				}			}			in_uint8a(s, packet.p, len);			packet.p += len;		}		/* Packet fully assembled */		if (packet.p == packet.end)		{			packet.p = packet.data;			rdpsnd_process_packet(packet_opcode, &packet);			packet.size = 0;		}	}}static RD_BOOLrdpsnddbg_line_handler(const char *line, void *data){#ifdef WITH_DEBUG_SOUND	fprintf(stderr, "SNDDBG: %s\n", line);#endif	return True;}static voidrdpsnddbg_process(STREAM s){	unsigned int pkglen;	static char *rest = NULL;	char *buf;	pkglen = s->end - s->p;	/* str_handle_lines requires null terminated strings */	buf = (char *) xmalloc(pkglen + 1);	STRNCPY(buf, (char *) s->p, pkglen + 1);	str_handle_lines(buf, &rest, rdpsnddbg_line_handler, NULL);	xfree(buf);}static voidrdpsnd_register_drivers(char *options){	struct audio_driver **reg;	/* The order of registrations define the probe-order	   when opening the device for the first time */	reg = &drivers;#if defined(RDPSND_ALSA)	*reg = alsa_register(options);	assert(*reg);	reg = &((*reg)->next);#endif#if defined(RDPSND_SUN)	*reg = sun_register(options);	assert(*reg);	reg = &((*reg)->next);#endif#if defined(RDPSND_OSS)	*reg = oss_register(options);	assert(*reg);	reg = &((*reg)->next);#endif#if defined(RDPSND_SGI)	*reg = sgi_register(options);	assert(*reg);	reg = &((*reg)->next);#endif#if defined(RDPSND_LIBAO)	*reg = libao_register(options);	assert(*reg);	reg = &((*reg)->next);#endif	*reg = NULL;}RD_BOOLrdpsnd_init(char *optarg){	struct audio_driver *pos;	char *driver = NULL, *options = NULL;	drivers = NULL;	packet.data = (uint8 *) xmalloc(65536);	packet.p = packet.end = packet.data;	packet.size = 0;	rdpsnd_channel =		channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,				 rdpsnd_process);	rdpsnddbg_channel =		channel_register("snddbg", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,				 rdpsnddbg_process);	if ((rdpsnd_channel == NULL) || (rdpsnddbg_channel == NULL))	{		error("channel_register\n");		return False;	}	rdpsnd_queue_init();	if (optarg != NULL && strlen(optarg) > 0)	{		driver = options = optarg;		while (*options != '\0' && *options != ':')			options++;		if (*options == ':')		{			*options = '\0';			options++;		}		if (*options == '\0')			options = NULL;	}	rdpsnd_register_drivers(options);	if (!driver)		return True;	pos = drivers;	while (pos != NULL)	{		if (!strcmp(pos->name, driver))		{			DEBUG(("selected %s\n", pos->name));			current_driver = pos;			return True;		}		pos = pos->next;	}	return False;}voidrdpsnd_show_help(void){	struct audio_driver *pos;	rdpsnd_register_drivers(NULL);	pos = drivers;	while (pos != NULL)	{		fprintf(stderr, "                     %s:\t%s\n", pos->name, pos->description);		pos = pos->next;	}}voidrdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv){	long next_pending;	if (device_open || rec_device_open)		current_driver->add_fds(n, rfds, wfds, tv);	next_pending = rdpsnd_queue_next_completion();	if (next_pending >= 0)	{		long cur_timeout;		cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;		if (cur_timeout > next_pending)		{			tv->tv_sec = next_pending / 1000000;			tv->tv_usec = next_pending % 1000000;		}	}}voidrdpsnd_check_fds(fd_set * rfds, fd_set * wfds){	rdpsnd_queue_complete_pending();	if (device_open || rec_device_open)		current_driver->check_fds(rfds, wfds);}static voidrdpsnd_queue_write(STREAM s, uint16 tick, uint8 index){	struct audio_packet *packet = &packet_queue[queue_hi];	unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;	if (next_hi == queue_pending)	{		error("No space to queue audio packet\n");		return;	}	queue_hi = next_hi;	packet->s = *s;	packet->tick = tick;	packet->index = index;	gettimeofday(&packet->arrive_tv, NULL);}struct audio_packet *rdpsnd_queue_current_packet(void){	return &packet_queue[queue_lo];}RD_BOOLrdpsnd_queue_empty(void){	return (queue_lo == queue_hi);}static voidrdpsnd_queue_init(void){	queue_pending = queue_lo = queue_hi = 0;}voidrdpsnd_queue_next(unsigned long completed_in_us){	struct audio_packet *packet;	assert(!rdpsnd_queue_empty());	packet = &packet_queue[queue_lo];	gettimeofday(&packet->completion_tv, NULL);	packet->completion_tv.tv_usec += completed_in_us;	packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;	packet->completion_tv.tv_usec %= 1000000;	queue_lo = (queue_lo + 1) % MAX_QUEUE;	rdpsnd_queue_complete_pending();}intrdpsnd_queue_next_tick(void){	if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)	{		return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;	}	else	{		return (packet_queue[queue_lo].tick + 65535) % 65536;	}}static voidrdpsnd_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;	}}static longrdpsnd_queue_next_completion(void){	struct audio_packet *packet;	long remaining;	struct timeval now;	if (queue_pending == queue_lo)		return -1;	gettimeofday(&now, NULL);	packet = &packet_queue[queue_pending];	remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +		(packet->completion_tv.tv_usec - now.tv_usec);	if (remaining < 0)		return 0;	return remaining;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -