📄 rdpsnd.c
字号:
{ 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 + -