unify queue-handling in rdpsnd.c (remove private copies from all
drivers) git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1253 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
parent
f4dce045b5
commit
ec4862937f
76
rdpsnd.c
76
rdpsnd.c
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "rdesktop.h"
|
#include "rdesktop.h"
|
||||||
|
#include "rdpsnd.h"
|
||||||
|
|
||||||
#define RDPSND_CLOSE 1
|
#define RDPSND_CLOSE 1
|
||||||
#define RDPSND_WRITE 2
|
#define RDPSND_WRITE 2
|
||||||
@ -30,6 +31,10 @@
|
|||||||
#define RDPSND_NEGOTIATE 7
|
#define RDPSND_NEGOTIATE 7
|
||||||
|
|
||||||
#define MAX_FORMATS 10
|
#define MAX_FORMATS 10
|
||||||
|
#define MAX_QUEUE 10
|
||||||
|
|
||||||
|
BOOL g_dsp_busy = False;
|
||||||
|
int g_dsp_fd;
|
||||||
|
|
||||||
static VCHANNEL *rdpsnd_channel;
|
static VCHANNEL *rdpsnd_channel;
|
||||||
|
|
||||||
@ -37,6 +42,8 @@ static BOOL device_open;
|
|||||||
static WAVEFORMATEX formats[MAX_FORMATS];
|
static WAVEFORMATEX formats[MAX_FORMATS];
|
||||||
static unsigned int format_count;
|
static unsigned int format_count;
|
||||||
static unsigned int current_format;
|
static unsigned int current_format;
|
||||||
|
static unsigned int queue_hi, queue_lo;
|
||||||
|
static struct audio_packet packet_queue[MAX_QUEUE];
|
||||||
|
|
||||||
static STREAM
|
static STREAM
|
||||||
rdpsnd_init_packet(uint16 type, uint16 size)
|
rdpsnd_init_packet(uint16 type, uint16 size)
|
||||||
@ -66,7 +73,7 @@ rdpsnd_send_completion(uint16 tick, uint8 packet_index)
|
|||||||
STREAM s;
|
STREAM s;
|
||||||
|
|
||||||
s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
|
s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
|
||||||
out_uint16_le(s, tick + 50);
|
out_uint16_le(s, tick);
|
||||||
out_uint8(s, packet_index);
|
out_uint8(s, packet_index);
|
||||||
out_uint8(s, 0);
|
out_uint8(s, 0);
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
@ -214,7 +221,7 @@ rdpsnd_process(STREAM s)
|
|||||||
current_format = format;
|
current_format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
wave_out_write(s, tick, packet_index);
|
rdpsnd_queue_write(s, tick, packet_index);
|
||||||
awaiting_data_packet = False;
|
awaiting_data_packet = False;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -260,5 +267,70 @@ rdpsnd_init(void)
|
|||||||
rdpsnd_channel =
|
rdpsnd_channel =
|
||||||
channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
|
channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
|
||||||
rdpsnd_process);
|
rdpsnd_process);
|
||||||
|
|
||||||
return (rdpsnd_channel != NULL);
|
return (rdpsnd_channel != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rdpsnd_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_lo)
|
||||||
|
{
|
||||||
|
error("No space to queue audio packet\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_hi = next_hi;
|
||||||
|
|
||||||
|
packet->s = *s;
|
||||||
|
packet->tick = tick;
|
||||||
|
packet->index = index;
|
||||||
|
packet->s.p += 4;
|
||||||
|
|
||||||
|
/* we steal the data buffer from s, give it a new one */
|
||||||
|
s->data = malloc(s->size);
|
||||||
|
|
||||||
|
if (!g_dsp_busy)
|
||||||
|
wave_out_play();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline struct audio_packet *
|
||||||
|
rdpsnd_queue_current_packet(void)
|
||||||
|
{
|
||||||
|
return &packet_queue[queue_lo];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BOOL
|
||||||
|
rdpsnd_queue_empty(void)
|
||||||
|
{
|
||||||
|
return (queue_lo == queue_hi);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
rdpsnd_queue_init(void)
|
||||||
|
{
|
||||||
|
queue_lo = queue_hi = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
rdpsnd_queue_next(void)
|
||||||
|
{
|
||||||
|
free(packet_queue[queue_lo].s.data);
|
||||||
|
queue_lo = (queue_lo + 1) % MAX_QUEUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int
|
||||||
|
rdpsnd_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
36
rdpsnd.h
Normal file
36
rdpsnd.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
rdesktop: A Remote Desktop Protocol client.
|
||||||
|
Sound infrastructure
|
||||||
|
Copyright (C) Michael Gernoth 2006
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct audio_packet
|
||||||
|
{
|
||||||
|
struct stream s;
|
||||||
|
uint16 tick;
|
||||||
|
uint8 index;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern BOOL g_dsp_busy;
|
||||||
|
extern int g_dsp_fd;
|
||||||
|
|
||||||
|
void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
|
||||||
|
inline struct audio_packet *rdpsnd_queue_current_packet(void);
|
||||||
|
inline BOOL rdpsnd_queue_empty(void);
|
||||||
|
inline void rdpsnd_queue_init(void);
|
||||||
|
inline void rdpsnd_queue_next(void);
|
||||||
|
inline int rdpsnd_queue_next_tick(void);
|
@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "rdesktop.h"
|
#include "rdesktop.h"
|
||||||
|
#include "rdpsnd.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -28,25 +29,14 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#define DEFAULTDEVICE "default"
|
#define DEFAULTDEVICE "default"
|
||||||
#define MAX_QUEUE 10
|
|
||||||
#define MAX_FRAMES 32
|
#define MAX_FRAMES 32
|
||||||
|
|
||||||
int g_dsp_fd;
|
|
||||||
BOOL g_dsp_busy = False;
|
|
||||||
static snd_pcm_t *pcm_handle = NULL;
|
static snd_pcm_t *pcm_handle = NULL;
|
||||||
static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
|
static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
|
||||||
static BOOL reopened;
|
static BOOL reopened;
|
||||||
static short samplewidth;
|
static short samplewidth;
|
||||||
static int audiochannels;
|
static int audiochannels;
|
||||||
|
|
||||||
static struct audio_packet
|
|
||||||
{
|
|
||||||
struct stream s;
|
|
||||||
uint16 tick;
|
|
||||||
uint8 index;
|
|
||||||
} packet_queue[MAX_QUEUE];
|
|
||||||
static unsigned int queue_hi, queue_lo;
|
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
wave_out_open(void)
|
wave_out_open(void)
|
||||||
{
|
{
|
||||||
@ -62,7 +52,7 @@ wave_out_open(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_dsp_fd = 0;
|
g_dsp_fd = 0;
|
||||||
queue_lo = queue_hi = 0;
|
rdpsnd_queue_init();
|
||||||
|
|
||||||
reopened = True;
|
reopened = True;
|
||||||
|
|
||||||
@ -73,13 +63,14 @@ void
|
|||||||
wave_out_close(void)
|
wave_out_close(void)
|
||||||
{
|
{
|
||||||
/* Ack all remaining packets */
|
/* Ack all remaining packets */
|
||||||
while (queue_lo != queue_hi)
|
while (!rdpsnd_queue_empty())
|
||||||
{
|
{
|
||||||
rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index);
|
rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick,
|
||||||
free(packet_queue[queue_lo].s.data);
|
rdpsnd_queue_current_packet()->index);
|
||||||
queue_lo = (queue_lo + 1) % MAX_QUEUE;
|
rdpsnd_queue_next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (pcm_handle)
|
if (pcm_handle)
|
||||||
{
|
{
|
||||||
snd_pcm_drop(pcm_handle);
|
snd_pcm_drop(pcm_handle);
|
||||||
@ -230,32 +221,6 @@ wave_out_volume(uint16 left, uint16 right)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
wave_out_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_lo)
|
|
||||||
{
|
|
||||||
error("No space to queue audio packet\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
queue_hi = next_hi;
|
|
||||||
|
|
||||||
packet->s = *s;
|
|
||||||
packet->tick = tick;
|
|
||||||
packet->index = index;
|
|
||||||
packet->s.p += 4;
|
|
||||||
|
|
||||||
/* we steal the data buffer from s, give it a new one */
|
|
||||||
s->data = (uint8 *) malloc(s->size);
|
|
||||||
|
|
||||||
if (!g_dsp_busy)
|
|
||||||
wave_out_play();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
wave_out_play(void)
|
wave_out_play(void)
|
||||||
{
|
{
|
||||||
@ -275,23 +240,16 @@ wave_out_play(void)
|
|||||||
prev_us = tv.tv_usec;
|
prev_us = tv.tv_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queue_lo == queue_hi)
|
if (rdpsnd_queue_empty())
|
||||||
{
|
{
|
||||||
g_dsp_busy = 0;
|
g_dsp_busy = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet = &packet_queue[queue_lo];
|
packet = rdpsnd_queue_current_packet();
|
||||||
out = &packet->s;
|
out = &packet->s;
|
||||||
|
|
||||||
if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
|
next_tick = rdpsnd_queue_next_tick();
|
||||||
{
|
|
||||||
next_tick = packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
next_tick = (packet->tick + 65535) % 65536;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = (out->end - out->p) / (samplewidth * audiochannels);
|
len = (out->end - out->p) / (samplewidth * audiochannels);
|
||||||
if ((len = snd_pcm_writei(pcm_handle, out->p, ((MAX_FRAMES < len) ? MAX_FRAMES : len))) < 0)
|
if ((len = snd_pcm_writei(pcm_handle, out->p, ((MAX_FRAMES < len) ? MAX_FRAMES : len))) < 0)
|
||||||
@ -320,11 +278,8 @@ wave_out_play(void)
|
|||||||
(packet->tick + duration) % 65536, next_tick % 65536));
|
(packet->tick + duration) % 65536, next_tick % 65536));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Until all drivers are using the windows sound-ticks, we need to
|
rdpsnd_send_completion(((packet->tick + duration) % 65536), packet->index);
|
||||||
substract the 50 ticks added later by rdpsnd.c */
|
rdpsnd_queue_next();
|
||||||
rdpsnd_send_completion(((packet->tick + duration) % 65536) - 50, packet->index);
|
|
||||||
free(out->data);
|
|
||||||
queue_lo = (queue_lo + 1) % MAX_QUEUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_dsp_busy = 1;
|
g_dsp_busy = 1;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
Sound Channel Process Functions - libao-driver
|
Sound Channel Process Functions - libao-driver
|
||||||
Copyright (C) Matthew Chapman 2003
|
Copyright (C) Matthew Chapman 2003
|
||||||
Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
|
Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
|
||||||
Copyright (C) Michael Gernoth mike@zerfleddert.de 2005
|
Copyright (C) Michael Gernoth mike@zerfleddert.de 2005-2006
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -21,17 +21,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "rdesktop.h"
|
#include "rdesktop.h"
|
||||||
|
#include "rdpsnd.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ao/ao.h>
|
#include <ao/ao.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#define MAX_QUEUE 10
|
|
||||||
#define WAVEOUTBUF 16
|
#define WAVEOUTBUF 16
|
||||||
|
|
||||||
int g_dsp_fd;
|
|
||||||
BOOL g_dsp_busy = False;
|
|
||||||
static ao_device *o_device = NULL;
|
static ao_device *o_device = NULL;
|
||||||
static int default_driver;
|
static int default_driver;
|
||||||
static int samplerate;
|
static int samplerate;
|
||||||
@ -39,14 +37,6 @@ static int audiochannels;
|
|||||||
static BOOL reopened;
|
static BOOL reopened;
|
||||||
static short samplewidth;
|
static short samplewidth;
|
||||||
|
|
||||||
static struct audio_packet
|
|
||||||
{
|
|
||||||
struct stream s;
|
|
||||||
uint16 tick;
|
|
||||||
uint8 index;
|
|
||||||
} packet_queue[MAX_QUEUE];
|
|
||||||
static unsigned int queue_hi, queue_lo;
|
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
wave_out_open(void)
|
wave_out_open(void)
|
||||||
{
|
{
|
||||||
@ -69,7 +59,7 @@ wave_out_open(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_dsp_fd = 0;
|
g_dsp_fd = 0;
|
||||||
queue_lo = queue_hi = 0;
|
rdpsnd_queue_init();
|
||||||
|
|
||||||
reopened = True;
|
reopened = True;
|
||||||
|
|
||||||
@ -80,11 +70,11 @@ void
|
|||||||
wave_out_close(void)
|
wave_out_close(void)
|
||||||
{
|
{
|
||||||
/* Ack all remaining packets */
|
/* Ack all remaining packets */
|
||||||
while (queue_lo != queue_hi)
|
while (!rdpsnd_queue_empty())
|
||||||
{
|
{
|
||||||
rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index);
|
rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick,
|
||||||
free(packet_queue[queue_lo].s.data);
|
rdpsnd_queue_current_packet()->index);
|
||||||
queue_lo = (queue_lo + 1) % MAX_QUEUE;
|
rdpsnd_queue_next();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o_device != NULL)
|
if (o_device != NULL)
|
||||||
@ -144,32 +134,6 @@ wave_out_volume(uint16 left, uint16 right)
|
|||||||
warning("volume changes not supported with libao-output\n");
|
warning("volume changes not supported with libao-output\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
wave_out_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_lo)
|
|
||||||
{
|
|
||||||
error("No space to queue audio packet\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
queue_hi = next_hi;
|
|
||||||
|
|
||||||
packet->s = *s;
|
|
||||||
packet->tick = tick;
|
|
||||||
packet->index = index;
|
|
||||||
packet->s.p += 4;
|
|
||||||
|
|
||||||
/* we steal the data buffer from s, give it a new one */
|
|
||||||
s->data = malloc(s->size);
|
|
||||||
|
|
||||||
if (!g_dsp_busy)
|
|
||||||
wave_out_play();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
wave_out_play(void)
|
wave_out_play(void)
|
||||||
{
|
{
|
||||||
@ -190,23 +154,16 @@ wave_out_play(void)
|
|||||||
prev_us = tv.tv_usec;
|
prev_us = tv.tv_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queue_lo == queue_hi)
|
if (rdpsnd_queue_empty())
|
||||||
{
|
{
|
||||||
g_dsp_busy = 0;
|
g_dsp_busy = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet = &packet_queue[queue_lo];
|
packet = rdpsnd_queue_current_packet();
|
||||||
out = &packet->s;
|
out = &packet->s;
|
||||||
|
|
||||||
if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
|
next_tick = rdpsnd_queue_next_tick();
|
||||||
{
|
|
||||||
next_tick = packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
next_tick = (packet->tick + 65535) % 65536;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
@ -261,11 +218,8 @@ wave_out_play(void)
|
|||||||
(packet->tick + duration) % 65536, next_tick % 65536));
|
(packet->tick + duration) % 65536, next_tick % 65536));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Until all drivers are using the windows sound-ticks, we need to
|
rdpsnd_send_completion(((packet->tick + duration) % 65536), packet->index);
|
||||||
substract the 50 ticks added later by rdpsnd.c */
|
rdpsnd_queue_next();
|
||||||
rdpsnd_send_completion(((packet->tick + duration) % 65536) - 50, packet->index);
|
|
||||||
free(out->data);
|
|
||||||
queue_lo = (queue_lo + 1) % MAX_QUEUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_dsp_busy = 1;
|
g_dsp_busy = 1;
|
||||||
|
52
rdpsnd_oss.c
52
rdpsnd_oss.c
@ -28,6 +28,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "rdesktop.h"
|
#include "rdesktop.h"
|
||||||
|
#include "rdpsnd.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -35,22 +36,12 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/soundcard.h>
|
#include <sys/soundcard.h>
|
||||||
|
|
||||||
|
#define DEFAULTDEVICE "/dev/dsp"
|
||||||
#define MAX_LEN 512
|
#define MAX_LEN 512
|
||||||
#define MAX_QUEUE 10
|
|
||||||
|
|
||||||
int g_dsp_fd;
|
|
||||||
BOOL g_dsp_busy = False;
|
|
||||||
static int snd_rate;
|
static int snd_rate;
|
||||||
static short samplewidth;
|
static short samplewidth;
|
||||||
|
|
||||||
static struct audio_packet
|
|
||||||
{
|
|
||||||
struct stream s;
|
|
||||||
uint16 tick;
|
|
||||||
uint8 index;
|
|
||||||
} packet_queue[MAX_QUEUE];
|
|
||||||
static unsigned int queue_hi, queue_lo;
|
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
wave_out_open(void)
|
wave_out_open(void)
|
||||||
{
|
{
|
||||||
@ -58,7 +49,7 @@ wave_out_open(void)
|
|||||||
|
|
||||||
if (dsp_dev == NULL)
|
if (dsp_dev == NULL)
|
||||||
{
|
{
|
||||||
dsp_dev = xstrdup("/dev/dsp");
|
dsp_dev = xstrdup(DEFAULTDEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((g_dsp_fd = open(dsp_dev, O_WRONLY)) == -1)
|
if ((g_dsp_fd = open(dsp_dev, O_WRONLY)) == -1)
|
||||||
@ -200,32 +191,6 @@ wave_out_volume(uint16 left, uint16 right)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
wave_out_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_lo)
|
|
||||||
{
|
|
||||||
error("No space to queue audio packet\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
queue_hi = next_hi;
|
|
||||||
|
|
||||||
packet->s = *s;
|
|
||||||
packet->tick = tick;
|
|
||||||
packet->index = index;
|
|
||||||
packet->s.p += 4;
|
|
||||||
|
|
||||||
/* we steal the data buffer from s, give it a new one */
|
|
||||||
s->data = (uint8 *) malloc(s->size);
|
|
||||||
|
|
||||||
if (!g_dsp_busy)
|
|
||||||
wave_out_play();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
wave_out_play(void)
|
wave_out_play(void)
|
||||||
{
|
{
|
||||||
@ -237,13 +202,13 @@ wave_out_play(void)
|
|||||||
static BOOL started = False;
|
static BOOL started = False;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
if (queue_lo == queue_hi)
|
if (rdpsnd_queue_empty())
|
||||||
{
|
{
|
||||||
g_dsp_busy = 0;
|
g_dsp_busy = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet = &packet_queue[queue_lo];
|
packet = rdpsnd_queue_current_packet();
|
||||||
out = &packet->s;
|
out = &packet->s;
|
||||||
|
|
||||||
if (!started)
|
if (!started)
|
||||||
@ -277,9 +242,10 @@ wave_out_play(void)
|
|||||||
|
|
||||||
if (elapsed >= (duration * 85) / 100)
|
if (elapsed >= (duration * 85) / 100)
|
||||||
{
|
{
|
||||||
rdpsnd_send_completion(packet->tick, packet->index);
|
/* We need to add 50 to tell windows that time has passed while
|
||||||
free(out->data);
|
* playing this packet */
|
||||||
queue_lo = (queue_lo + 1) % MAX_QUEUE;
|
rdpsnd_send_completion(packet->tick + 50, packet->index);
|
||||||
|
rdpsnd_queue_next();
|
||||||
started = False;
|
started = False;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
89
rdpsnd_sgi.c
89
rdpsnd_sgi.c
@ -28,13 +28,9 @@
|
|||||||
|
|
||||||
#define IRIX_MAX_VOL 65535
|
#define IRIX_MAX_VOL 65535
|
||||||
|
|
||||||
#define MAX_QUEUE 10
|
|
||||||
|
|
||||||
int g_dsp_fd;
|
|
||||||
ALconfig audioconfig;
|
ALconfig audioconfig;
|
||||||
ALport output_port;
|
ALport output_port;
|
||||||
|
|
||||||
BOOL g_dsp_busy = False;
|
|
||||||
static BOOL g_swapaudio;
|
static BOOL g_swapaudio;
|
||||||
static int g_snd_rate;
|
static int g_snd_rate;
|
||||||
static BOOL g_swapaudio;
|
static BOOL g_swapaudio;
|
||||||
@ -44,56 +40,46 @@ double min_volume, max_volume, volume_range;
|
|||||||
int resource, maxFillable;
|
int resource, maxFillable;
|
||||||
int combinedFrameSize;
|
int combinedFrameSize;
|
||||||
|
|
||||||
static struct audio_packet
|
|
||||||
{
|
|
||||||
struct stream s;
|
|
||||||
uint16 tick;
|
|
||||||
uint8 index;
|
|
||||||
} packet_queue[MAX_QUEUE];
|
|
||||||
static unsigned int queue_hi, queue_lo;
|
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
wave_out_open(void)
|
wave_out_open(void)
|
||||||
{
|
{
|
||||||
ALparamInfo pinfo;
|
ALparamInfo pinfo;
|
||||||
|
|
||||||
#if (defined(IRIX_DEBUG))
|
#if (defined(IRIX_DEBUG))
|
||||||
fprintf(stderr, "wave_out_open: begin\n");
|
fprintf(stderr, "sgi_open: begin\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (alGetParamInfo(AL_DEFAULT_OUTPUT, AL_GAIN, &pinfo) < 0)
|
if (alGetParamInfo(AL_DEFAULT_OUTPUT, AL_GAIN, &pinfo) < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "wave_out_open: alGetParamInfo failed: %s\n",
|
fprintf(stderr, "sgi_open: alGetParamInfo failed: %s\n",
|
||||||
alGetErrorString(oserror()));
|
alGetErrorString(oserror()));
|
||||||
}
|
}
|
||||||
min_volume = alFixedToDouble(pinfo.min.ll);
|
min_volume = alFixedToDouble(pinfo.min.ll);
|
||||||
max_volume = alFixedToDouble(pinfo.max.ll);
|
max_volume = alFixedToDouble(pinfo.max.ll);
|
||||||
volume_range = (max_volume - min_volume);
|
volume_range = (max_volume - min_volume);
|
||||||
#if (defined(IRIX_DEBUG))
|
#if (defined(IRIX_DEBUG))
|
||||||
fprintf(stderr, "wave_out_open: minvol = %lf, maxvol= %lf, range = %lf.\n",
|
fprintf(stderr, "sgi_open: minvol = %lf, maxvol= %lf, range = %lf.\n",
|
||||||
min_volume, max_volume, volume_range);
|
min_volume, max_volume, volume_range);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
queue_lo = queue_hi = 0;
|
rdpsnd_queue_init();
|
||||||
|
|
||||||
audioconfig = alNewConfig();
|
audioconfig = alNewConfig();
|
||||||
if (audioconfig == (ALconfig) 0)
|
if (audioconfig == (ALconfig) 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "wave_out_open: alNewConfig failed: %s\n",
|
fprintf(stderr, "sgi_open: alNewConfig failed: %s\n", alGetErrorString(oserror()));
|
||||||
alGetErrorString(oserror()));
|
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
output_port = alOpenPort("rdpsnd", "w", 0);
|
output_port = alOpenPort("rdpsnd", "w", 0);
|
||||||
if (output_port == (ALport) 0)
|
if (output_port == (ALport) 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "wave_out_open: alOpenPort failed: %s\n",
|
fprintf(stderr, "sgi_open: alOpenPort failed: %s\n", alGetErrorString(oserror()));
|
||||||
alGetErrorString(oserror()));
|
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined(IRIX_DEBUG))
|
#if (defined(IRIX_DEBUG))
|
||||||
fprintf(stderr, "wave_out_open: returning\n");
|
fprintf(stderr, "sgi_open: returning\n");
|
||||||
#endif
|
#endif
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
@ -103,21 +89,23 @@ wave_out_close(void)
|
|||||||
{
|
{
|
||||||
/* Ack all remaining packets */
|
/* Ack all remaining packets */
|
||||||
#if (defined(IRIX_DEBUG))
|
#if (defined(IRIX_DEBUG))
|
||||||
fprintf(stderr, "wave_out_close: begin\n");
|
fprintf(stderr, "sgi_close: begin\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (queue_lo != queue_hi)
|
while (!rdpsnd_queue_empty())
|
||||||
{
|
{
|
||||||
rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index);
|
/* We need to add 50 to tell windows that time has passed while
|
||||||
free(packet_queue[queue_lo].s.data);
|
* playing this packet */
|
||||||
queue_lo = (queue_lo + 1) % MAX_QUEUE;
|
rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick + 50,
|
||||||
|
rdpsnd_queue_current_packet()->index);
|
||||||
|
rdpsnd_queue_next();
|
||||||
}
|
}
|
||||||
alDiscardFrames(output_port, 0);
|
alDiscardFrames(output_port, 0);
|
||||||
|
|
||||||
alClosePort(output_port);
|
alClosePort(output_port);
|
||||||
alFreeConfig(audioconfig);
|
alFreeConfig(audioconfig);
|
||||||
#if (defined(IRIX_DEBUG))
|
#if (defined(IRIX_DEBUG))
|
||||||
fprintf(stderr, "wave_out_close: returning\n");
|
fprintf(stderr, "sgi_close: returning\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +130,7 @@ wave_out_set_format(WAVEFORMATEX * pwfx)
|
|||||||
ALpv params;
|
ALpv params;
|
||||||
|
|
||||||
#if (defined(IRIX_DEBUG))
|
#if (defined(IRIX_DEBUG))
|
||||||
fprintf(stderr, "wave_out_set_format: init...\n");
|
fprintf(stderr, "sgi_set_format: init...\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_swapaudio = False;
|
g_swapaudio = False;
|
||||||
@ -178,7 +166,7 @@ wave_out_set_format(WAVEFORMATEX * pwfx)
|
|||||||
|
|
||||||
if (output_port == (ALport) 0)
|
if (output_port == (ALport) 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "wave_out_set_format: alOpenPort failed: %s\n",
|
fprintf(stderr, "sgi_set_format: alOpenPort failed: %s\n",
|
||||||
alGetErrorString(oserror()));
|
alGetErrorString(oserror()));
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
@ -192,7 +180,7 @@ wave_out_set_format(WAVEFORMATEX * pwfx)
|
|||||||
|
|
||||||
if (frameSize == 0 || channelCount == 0)
|
if (frameSize == 0 || channelCount == 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "wave_out_set_format: bad frameSize or channelCount\n");
|
fprintf(stderr, "sgi_set_format: bad frameSize or channelCount\n");
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
combinedFrameSize = frameSize * channelCount;
|
combinedFrameSize = frameSize * channelCount;
|
||||||
@ -213,7 +201,7 @@ wave_out_set_format(WAVEFORMATEX * pwfx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if (defined(IRIX_DEBUG))
|
#if (defined(IRIX_DEBUG))
|
||||||
fprintf(stderr, "wave_out_set_format: returning...\n");
|
fprintf(stderr, "sgi_set_format: returning...\n");
|
||||||
#endif
|
#endif
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
@ -226,7 +214,7 @@ wave_out_volume(uint16 left, uint16 right)
|
|||||||
ALfixed gain[8];
|
ALfixed gain[8];
|
||||||
|
|
||||||
#if (defined(IRIX_DEBUG))
|
#if (defined(IRIX_DEBUG))
|
||||||
fprintf(stderr, "wave_out_volume: begin\n");
|
fprintf(stderr, "sgi_volume: begin\n");
|
||||||
fprintf(stderr, "left='%d', right='%d'\n", left, right);
|
fprintf(stderr, "left='%d', right='%d'\n", left, right);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -241,42 +229,16 @@ wave_out_volume(uint16 left, uint16 right)
|
|||||||
pv[0].sizeIn = 8;
|
pv[0].sizeIn = 8;
|
||||||
if (alSetParams(AL_DEFAULT_OUTPUT, pv, 1) < 0)
|
if (alSetParams(AL_DEFAULT_OUTPUT, pv, 1) < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "wave_out_volume: alSetParams failed: %s\n",
|
fprintf(stderr, "sgi_volume: alSetParams failed: %s\n",
|
||||||
alGetErrorString(oserror()));
|
alGetErrorString(oserror()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined(IRIX_DEBUG))
|
#if (defined(IRIX_DEBUG))
|
||||||
fprintf(stderr, "wave_out_volume: returning\n");
|
fprintf(stderr, "sgi_volume: returning\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
wave_out_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_lo)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "No space to queue audio packet\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
queue_hi = next_hi;
|
|
||||||
|
|
||||||
packet->s = *s;
|
|
||||||
packet->tick = tick;
|
|
||||||
packet->index = index;
|
|
||||||
packet->s.p += 4;
|
|
||||||
|
|
||||||
/* we steal the data buffer from s, give it a new one */
|
|
||||||
s->data = malloc(s->size);
|
|
||||||
|
|
||||||
if (!g_dsp_busy)
|
|
||||||
wave_out_play();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
wave_out_play(void)
|
wave_out_play(void)
|
||||||
{
|
{
|
||||||
@ -290,13 +252,13 @@ wave_out_play(void)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (queue_lo == queue_hi)
|
if (rdpsnd_queue_empty())
|
||||||
{
|
{
|
||||||
g_dsp_busy = False;
|
g_dsp_busy = False;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet = &packet_queue[queue_lo];
|
packet = rdpsnd_queue_current_packet();
|
||||||
out = &packet->s;
|
out = &packet->s;
|
||||||
|
|
||||||
/* Swap the current packet, but only once */
|
/* Swap the current packet, but only once */
|
||||||
@ -322,8 +284,7 @@ wave_out_play(void)
|
|||||||
if (gf < (4 * maxFillable / 10))
|
if (gf < (4 * maxFillable / 10))
|
||||||
{
|
{
|
||||||
rdpsnd_send_completion(packet->tick, packet->index);
|
rdpsnd_send_completion(packet->tick, packet->index);
|
||||||
free(out->data);
|
rdpsnd_queue_next();
|
||||||
queue_lo = (queue_lo + 1) % MAX_QUEUE;
|
|
||||||
swapped = False;
|
swapped = False;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
64
rdpsnd_sun.c
64
rdpsnd_sun.c
@ -3,7 +3,7 @@
|
|||||||
Sound Channel Process Functions - Sun
|
Sound Channel Process Functions - Sun
|
||||||
Copyright (C) Matthew Chapman 2003
|
Copyright (C) Matthew Chapman 2003
|
||||||
Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
|
Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
|
||||||
Copyright (C) Michael Gernoth mike@zerfleddert.de 2003
|
Copyright (C) Michael Gernoth mike@zerfleddert.de 2003-2006
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "rdesktop.h"
|
#include "rdesktop.h"
|
||||||
|
#include "rdpsnd.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -31,22 +32,12 @@
|
|||||||
#include <stropts.h>
|
#include <stropts.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAX_QUEUE 10
|
#define DEFAULTDEVICE "/dev/audio"
|
||||||
|
|
||||||
int g_dsp_fd;
|
|
||||||
BOOL g_dsp_busy = False;
|
|
||||||
static BOOL g_reopened;
|
static BOOL g_reopened;
|
||||||
static BOOL g_swapaudio;
|
static BOOL g_swapaudio;
|
||||||
static short g_samplewidth;
|
static short g_samplewidth;
|
||||||
|
|
||||||
static struct audio_packet
|
|
||||||
{
|
|
||||||
struct stream s;
|
|
||||||
uint16 tick;
|
|
||||||
uint8 index;
|
|
||||||
} packet_queue[MAX_QUEUE];
|
|
||||||
static unsigned int queue_hi, queue_lo;
|
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
wave_out_open(void)
|
wave_out_open(void)
|
||||||
{
|
{
|
||||||
@ -54,7 +45,7 @@ wave_out_open(void)
|
|||||||
|
|
||||||
if (dsp_dev == NULL)
|
if (dsp_dev == NULL)
|
||||||
{
|
{
|
||||||
dsp_dev = xstrdup("/dev/audio");
|
dsp_dev = xstrdup(DEFAULTDEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
|
if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
|
||||||
@ -66,7 +57,7 @@ wave_out_open(void)
|
|||||||
/* Non-blocking so that user interface is responsive */
|
/* Non-blocking so that user interface is responsive */
|
||||||
fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
|
fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
|
||||||
|
|
||||||
queue_lo = queue_hi = 0;
|
rdpsnd_queue_init();
|
||||||
g_reopened = True;
|
g_reopened = True;
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
@ -76,11 +67,11 @@ void
|
|||||||
wave_out_close(void)
|
wave_out_close(void)
|
||||||
{
|
{
|
||||||
/* Ack all remaining packets */
|
/* Ack all remaining packets */
|
||||||
while (queue_lo != queue_hi)
|
while (!rdpsnd_queue_empty())
|
||||||
{
|
{
|
||||||
rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index);
|
rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick,
|
||||||
free(packet_queue[queue_lo].s.data);
|
rdpsnd_queue_current_packet()->index);
|
||||||
queue_lo = (queue_lo + 1) % MAX_QUEUE;
|
rdpsnd_queue_next();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined I_FLUSH && defined FLUSHW
|
#if defined I_FLUSH && defined FLUSHW
|
||||||
@ -192,32 +183,6 @@ wave_out_volume(uint16 left, uint16 right)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
wave_out_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_lo)
|
|
||||||
{
|
|
||||||
error("No space to queue audio packet\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
queue_hi = next_hi;
|
|
||||||
|
|
||||||
packet->s = *s;
|
|
||||||
packet->tick = tick;
|
|
||||||
packet->index = index;
|
|
||||||
packet->s.p += 4;
|
|
||||||
|
|
||||||
/* we steal the data buffer from s, give it a new one */
|
|
||||||
s->data = malloc(s->size);
|
|
||||||
|
|
||||||
if (!g_dsp_busy)
|
|
||||||
wave_out_play();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
wave_out_play(void)
|
wave_out_play(void)
|
||||||
{
|
{
|
||||||
@ -243,13 +208,13 @@ wave_out_play(void)
|
|||||||
g_reopened = False;
|
g_reopened = False;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queue_lo == queue_hi)
|
if (rdpsnd_queue_empty())
|
||||||
{
|
{
|
||||||
g_dsp_busy = 0;
|
g_dsp_busy = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet = &packet_queue[queue_lo];
|
packet = rdpsnd_queue_current_packet();
|
||||||
out = &packet->s;
|
out = &packet->s;
|
||||||
|
|
||||||
/* Swap the current packet, but only once */
|
/* Swap the current packet, but only once */
|
||||||
@ -297,9 +262,10 @@ wave_out_play(void)
|
|||||||
if (info.play.samples >= samplecnt + ((numsamples * 7) / 10))
|
if (info.play.samples >= samplecnt + ((numsamples * 7) / 10))
|
||||||
{
|
{
|
||||||
samplecnt += numsamples;
|
samplecnt += numsamples;
|
||||||
rdpsnd_send_completion(packet->tick, packet->index);
|
/* We need to add 50 to tell windows that time has passed while
|
||||||
free(out->data);
|
* playing this packet */
|
||||||
queue_lo = (queue_lo + 1) % MAX_QUEUE;
|
rdpsnd_send_completion(packet->tick + 50, packet->index);
|
||||||
|
rdpsnd_queue_next();
|
||||||
swapped = False;
|
swapped = False;
|
||||||
sentcompletion = True;
|
sentcompletion = True;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user