--- rdpsnd_oss.c.orig	2007-08-20 23:20:40.000000000 -0700
+++ rdpsnd_oss.c	2007-08-20 23:21:51.000000000 -0700
@@ -51,6 +51,35 @@
 } packet_queue[MAX_QUEUE];
 static unsigned int queue_hi, queue_lo;
 
+/** Frees the first audio packet in the queue (that is, packet_queue[queue_lo]),
+ * sending a completion notification back to the server.
+ *
+ * @return True if the packet queue has become empty; False otherwise. 
+ *
+ * If the packet queue is not empty, queue_lo will point at the next packet to
+ * play.
+ */
+static BOOL
+packet_done(void)
+{
+	struct audio_packet *packet = &packet_queue[queue_lo++];
+	queue_lo %= MAX_QUEUE;
+	rdpsnd_send_completion(packet->tick, packet->index);
+	free(packet->s.data);
+	return (queue_lo == queue_hi);
+}
+
+/** Discards all audio packets queued, sending completion notifications back to
+ * the server as necessary.
+ */
+static void
+clear_queue(void)
+{
+	while (queue_lo != queue_hi)
+		packet_done();
+	g_dsp_busy = False;
+}
+
 BOOL
 wave_out_open(void)
 {
@@ -74,6 +103,7 @@
 wave_out_close(void)
 {
 	close(g_dsp_fd);
+	clear_queue();
 }
 
 BOOL
@@ -277,9 +307,7 @@
 
 		if (elapsed >= (duration * 85) / 100)
 		{
-			rdpsnd_send_completion(packet->tick, packet->index);
-			free(out->data);
-			queue_lo = (queue_lo + 1) % MAX_QUEUE;
+			packet_done();
 			started = False;
 		}
 		else


syntax highlighted by Code2HTML, v. 0.9.1