public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
From: "Frédéric DALLEAU" <frederic.dalleau@palmsource.com>
To: BlueZ development <bluez-devel@lists.sourceforge.net>
Subject: [Bluez-devel]  Big patch to a2dpd
Date: Thu, 31 Aug 2006 18:04:31 +0200	[thread overview]
Message-ID: <44F7088F.6090606@palmsource.com> (raw)
In-Reply-To: <44F5A472.30003@xmission.com>

[-- Attachment #1: Type: text/plain, Size: 678 bytes --]

Hi Brad,
>
> I looked over Matthew's patches and applied them. I applied your "small
> patch" which turns out to be bigger than it sounds :)
>   
This one is more than bigger!
Reindent,
Alsa output redirection,
New on-the-fly in-play switch from bt to alsa and reverse
Changing bdaddr in play too.
More options described in sample.a2dprc

I removed the line LIBS= from Makefile.am as suggested. This line was 
making tons of compilation problems. As a2dpd finally links to alsa, it 
is no longer needed.
Please give it a try before submitting (Matthew and RUI if you read that).

Wrote a doc : http://fdalleau.free.fr/a2dp_doc.pdf ideas welcome!

Frédéric


[-- Attachment #2: patch_btsco_alsaredirect --]
[-- Type: text/plain, Size: 196899 bytes --]

? Doxyfile
? Makefile.in
? aclocal.m4
? autom4te.cache
? btsco.kdevelop
? btsco.kdevelop.pcs
? btsco.kdevses
? compile
? config.guess
? config.h.in
? config.sub
? configure
? depcomp
? install-sh
? missing
? alsa-plugins/Makefile.in
? avdtp/Makefile.in
? sbc/Makefile.in
Index: alsa-plugins/BUILD
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/alsa-plugins/BUILD,v
retrieving revision 1.2
diff -u -r1.2 BUILD
--- alsa-plugins/BUILD	12 Aug 2006 01:51:54 -0000	1.2
+++ alsa-plugins/BUILD	31 Aug 2006 15:58:56 -0000
@@ -26,4 +26,3 @@
 Note that this device will not automatically appear in the list of alsa devices.
 The alsa folks did this by design but they added a new api for clients to 
 enumerate plugin devices.
-
Index: alsa-plugins/Makefile.am
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/alsa-plugins/Makefile.am,v
retrieving revision 1.6
diff -u -r1.6 Makefile.am
--- alsa-plugins/Makefile.am	6 Aug 2006 05:23:43 -0000	1.6
+++ alsa-plugins/Makefile.am	31 Aug 2006 15:58:56 -0000
@@ -4,8 +4,6 @@
 
 if ALSAPLUGIN
 
-#LIBS = 
-
 alsadir = $(libdir)/alsa-lib
 
 alsa_LTLIBRARIES = libasound_module_pcm_a2dp.la libasound_module_pcm_a2dpd.la libasound_module_ctl_a2dpd.la libasound_module_pcm_sco.la libasound_module_ctl_sco.la
@@ -31,9 +29,10 @@
 libasound_module_ctl_sco_la_LIBADD = @ALSA_LIBS@
 
 bin_PROGRAMS = a2dpd
-a2dpd_SOURCES = a2dpd.c a2dplib.c 
+a2dpd_SOURCES = a2dpd.c a2dplib.c alsalib.c
+a2dpd_CFLAGS = $(AM_CFLAGS)
 #a2dp_timer.c a2dp_ipc.c
-a2dpd_LDADD = a2dp_timer.o a2dp_ipc.o @BLUEZ_LIBS@ -lsbc -lpthread -lrt
+a2dpd_LDADD = a2dp_timer.o a2dp_ipc.o @ALSA_LIBS@ @BLUEZ_LIBS@ -lsbc -lpthread -lrt
 
 AM_CFLAGS = @ALSA_CFLAGS@ @BLUEZ_CFLAGS@ -pthread
 AM_LDFLAGS = -module -avoid-version -export-dynamic
Index: alsa-plugins/a2dp_ipc.c
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/alsa-plugins/a2dp_ipc.c,v
retrieving revision 1.3
diff -u -r1.3 a2dp_ipc.c
--- alsa-plugins/a2dp_ipc.c	17 Aug 2006 14:06:27 -0000	1.3
+++ alsa-plugins/a2dp_ipc.c	31 Aug 2006 15:58:56 -0000
@@ -36,7 +36,11 @@
 
 void close_socket(int sockfd)
 {
-        if(sockfd>0) close(sockfd);
+        if(sockfd>0)
+        {
+        	shutdown(sockfd, SHUT_RDWR);
+        	close(sockfd);
+        }
 }
 
 int make_udp_socket()
@@ -98,7 +102,7 @@
         {
                 if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))==0)
                 {
-                        if(listen(sockfd, 10)==0)
+                        if(listen(sockfd, 0)==0)
                         {
                                 // No error
                         }
Index: alsa-plugins/a2dp_timer.c
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/alsa-plugins/a2dp_timer.c,v
retrieving revision 1.2
diff -u -r1.2 a2dp_timer.c
--- alsa-plugins/a2dp_timer.c	17 Aug 2006 14:06:27 -0000	1.2
+++ alsa-plugins/a2dp_timer.c	31 Aug 2006 15:58:56 -0000
@@ -26,104 +26,93 @@
 #include <unistd.h>
 #include <syslog.h>
 
-void sleeptodate(LPTIMERINFO lpTimerInfo, struct timeval* date, int predelay)
+void sleeptodate(LPTIMERINFO lpTimerInfo, struct timeval *date, int predelay)
 {
-        struct timeval now;
-        struct timeval resolutionval={0, predelay + (int)(lpTimerInfo->timer_resolution.tv_nsec/1000)};
+	struct timeval now;
+	struct timeval resolutionval = { 0, predelay + (int) (lpTimerInfo->timer_resolution.tv_nsec / 1000) };
 
-        // See if we have time to wait
-        timeradd(&lpTimerInfo->timeofday, &resolutionval, &now);
-        if (timercmp(date, &now, >))
-        {
-                // Synchronise with usleep 20 ms cycle
-                usleep(1);
-                // See if we must wait again
-                gettimeofday(&now, NULL);
-                timeradd(&now, &resolutionval, &now);
-                if (timercmp(date, &now, >))
-                {
-                        struct timeval interval = { 0, 0 };
-                        timersub(date, &now, &interval);
-                        // sleep
-                        usleep(interval.tv_usec);
-                }
-        }
-        else
-        {
-                // We're late, do not wait
-        }
+	// See if we have time to wait
+	timeradd(&lpTimerInfo->timeofday, &resolutionval, &now);
+	if (timercmp(date, &now, >)) {
+		// Synchronise with usleep 20 ms cycle
+		usleep(1);
+		// See if we must wait again
+		gettimeofday(&now, NULL);
+		timeradd(&now, &resolutionval, &now);
+		if (timercmp(date, &now, >)) {
+			struct timeval interval = { 0, 0 };
+			timersub(date, &now, &interval);
+			// sleep
+			usleep(interval.tv_usec);
+		}
+	} else {
+		// We're late, do not wait
+	}
 }
 
 // This version uses values never reset
 void keepfreqtotal(LPTIMERINFO lpTimerInfo, int predelay)
 {
-        struct timeval playtime, theoricaldate;
+	struct timeval playtime, theoricaldate;
 
-        //FIXME It is not necessary to use unsigned long if we reset periodically the value of itotalcount (see MAXTOTALCOUNT)
-        // if MAXTOTALCOUNT < 700000, we will fit in signed 32bit and reset no more than every 36 mins.
-        // Resetting that value might cause a small sound break.
-        // Setting MAXTOTALCOUNT to lpTimerInfo->fps will reset every second (useful for testing purposes)
-        playtime.tv_sec=((unsigned long)((1.0*(lpTimerInfo->itotalcount)/lpTimerInfo->fps)));
-        playtime.tv_usec=((unsigned long)((1.0*1000.0*1000.0/lpTimerInfo->fps)*(lpTimerInfo->itotalcount)))%1000000;
-        timeradd(&lpTimerInfo->totalcounter, &playtime, &theoricaldate);
-
-        // Si la date théorique est supérieure à la date actuelle
-        if(timercmp(&theoricaldate, &lpTimerInfo->timeofday, >))
-        {
-                sleeptodate(lpTimerInfo, &theoricaldate, predelay);
-        }
+	//FIXME It is not necessary to use unsigned long if we reset periodically the value of itotalcount (see MAXTOTALCOUNT)
+	// if MAXTOTALCOUNT < 700000, we will fit in signed 32bit and reset no more than every 36 mins.
+	// Resetting that value might cause a small sound break.
+	// Setting MAXTOTALCOUNT to lpTimerInfo->fps will reset every second (useful for testing purposes)
+	playtime.tv_sec = ((unsigned long) ((1.0 * (lpTimerInfo->itotalcount) / lpTimerInfo->fps)));
+	playtime.tv_usec = ((unsigned long) ((1.0 * 1000.0 * 1000.0 / lpTimerInfo->fps) * (lpTimerInfo->itotalcount))) % 1000000;
+	timeradd(&lpTimerInfo->totalcounter, &playtime, &theoricaldate);
+
+	// If calculated date is higher than current date
+	if (timercmp(&theoricaldate, &lpTimerInfo->timeofday, >)) {
+		sleeptodate(lpTimerInfo, &theoricaldate, predelay);
+	}
 }
 
 void a2dp_timer_notifyframe(LPTIMERINFO lpTimerInfo)
 {
-        struct timeval lastframe_interval = {0,0};
-        struct timeval maxallowed_interval = {0,200*1000};
-        gettimeofday(&lpTimerInfo->timeofday, NULL);
-        timersub(&lpTimerInfo->timeofday, &lpTimerInfo->lastframe, &lastframe_interval);
-        // Previous frames older than 1 second, reset counters
-        if(timercmp(&lastframe_interval, &maxallowed_interval, >))
-        {
-                // We must reset the total counter because else, we will believe the date is late
-                gettimeofday(&lpTimerInfo->totalcounter, NULL);
-                lpTimerInfo->itotalcount=0;
-        }
-        gettimeofday(&lpTimerInfo->lastframe, NULL);
+	struct timeval lastframe_interval = { 0, 0 };
+	struct timeval maxallowed_interval = { 0, 200 * 1000 };
+	gettimeofday(&lpTimerInfo->timeofday, NULL);
+	timersub(&lpTimerInfo->timeofday, &lpTimerInfo->lastframe, &lastframe_interval);
+	// Previous frames older than 1 second, reset counters
+	if (timercmp(&lastframe_interval, &maxallowed_interval, >)) {
+		// We must reset the total counter because else, we will believe the date is late
+		gettimeofday(&lpTimerInfo->totalcounter, NULL);
+		lpTimerInfo->itotalcount = 0;
+	}
+	gettimeofday(&lpTimerInfo->lastframe, NULL);
 }
 
 void a2dp_timer_sleep(LPTIMERINFO lpTimerInfo, int predelay)
 {
-        gettimeofday(&lpTimerInfo->timeofday, NULL);
+	gettimeofday(&lpTimerInfo->timeofday, NULL);
 
-        // Initialize timers
-        if(lpTimerInfo->staticcounter.tv_sec==0)
-                gettimeofday(&lpTimerInfo->staticcounter, NULL);
-        if(lpTimerInfo->totalcounter.tv_sec==0 || lpTimerInfo->itotalcount>MAXTOTALCOUNT)
-        {
-                gettimeofday(&lpTimerInfo->totalcounter, NULL);
-                lpTimerInfo->itotalcount=0;
-        }
-        if(lpTimerInfo->timer_resolution.tv_nsec == 0)
-                clock_getres(CLOCK_REALTIME, &lpTimerInfo->timer_resolution);
-
-        // Duration since last call
-        timersub(&lpTimerInfo->timeofday, &lpTimerInfo->staticcounter, &lpTimerInfo->duration);
-
-        // Display data once per second
-        if(lpTimerInfo->duration.tv_sec>0)
-        {
-                // Reset all statistics
-                gettimeofday(&lpTimerInfo->staticcounter, NULL);
-                lpTimerInfo->display=lpTimerInfo->icount;
-                lpTimerInfo->icount=0;
-        }
-        else
-        {
-                lpTimerInfo->display=0;
-        }
+	// Initialize timers
+	if (lpTimerInfo->staticcounter.tv_sec == 0)
+		gettimeofday(&lpTimerInfo->staticcounter, NULL);
+	if (lpTimerInfo->totalcounter.tv_sec == 0 || lpTimerInfo->itotalcount > MAXTOTALCOUNT) {
+		gettimeofday(&lpTimerInfo->totalcounter, NULL);
+		lpTimerInfo->itotalcount = 0;
+	}
+	if (lpTimerInfo->timer_resolution.tv_nsec == 0)
+		clock_getres(CLOCK_REALTIME, &lpTimerInfo->timer_resolution);
+
+	// Duration since last call
+	timersub(&lpTimerInfo->timeofday, &lpTimerInfo->staticcounter, &lpTimerInfo->duration);
+
+	// Display data once per second
+	if (lpTimerInfo->duration.tv_sec > 0) {
+		// Reset all statistics
+		gettimeofday(&lpTimerInfo->staticcounter, NULL);
+		lpTimerInfo->display = lpTimerInfo->icount;
+		lpTimerInfo->icount = 0;
+	} else {
+		lpTimerInfo->display = 0;
+	}
 
-        keepfreqtotal(lpTimerInfo, predelay);
+	keepfreqtotal(lpTimerInfo, predelay);
 
-        lpTimerInfo->icount++;
-        lpTimerInfo->itotalcount++;
+	lpTimerInfo->icount++;
+	lpTimerInfo->itotalcount++;
 }
-
Index: alsa-plugins/a2dpair
===================================================================
RCS file: alsa-plugins/a2dpair
diff -N alsa-plugins/a2dpair
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ alsa-plugins/a2dpair	31 Aug 2006 15:58:57 -0000
@@ -0,0 +1,129 @@
+#!/bin/sh
+
+#
+# Discovery
+#
+echo "Discovery in progress..."
+I=0
+SCANFILE=/tmp/hci_scan
+declare -a ARRAYADDR
+declare -a ARRAYNAME
+
+# We need this file because else there is a problem with arrays in shell
+# The while loop is run in a subshell
+hcitool scan > $SCANFILE
+
+while read BTADDR BTDESC ; do
+	if expr match "$BTADDR" "..:..:..:..:..:.." > /dev/null ; then
+		# Truc
+		echo "$I) [$BTADDR] $BTDESC" 
+		I=`expr $I + 1`
+		ARRAYADDR[$I]="$BTADDR"
+		ARRAYNAME[$I]="$BTDESC"
+	fi
+done < $SCANFILE
+rm -f $SCANFILE
+
+if [ $I -le 0 ] ; then
+	echo "Found $I devices"
+	exit -1
+fi
+
+#
+# Device selection
+#
+SELECTION=
+I=`expr $I - 1`
+while [ -z $SELECTION ] || [ $SELECTION -gt $I ] ; do
+	echo "Choose device (0-$I)"
+	read SELECTION
+done
+# sh uses 1 based arrays
+SELECTION=`expr $SELECTION + 1`
+ADDRESS=${ARRAYADDR[$SELECTION]}
+NAME=${ARRAYNAME[$SELECTION]}
+#
+# Pairing
+#
+echo "Pair device $NAME (y/N)?"
+read CANPAIR
+
+if [ "$CANPAIR" = "y" ] ; then
+	
+	# Device passkey
+	SELECTION=
+	while [ -z $SELECTION ] ; do
+		echo "Enter passkey for $NAME"
+		read SELECTION
+	done
+	PASSKEY=$SELECTION
+	
+	# Prefetch password
+	sudo echo "Pairing in progress..."
+	
+	# passkey agent
+	if sudo passkey-agent --default $PASSKEY & PASSPID=$! ; then
+	
+		#echo "Registered passkey-agent pid=$PASSPID"
+	
+		# pairing
+		ANYTEXTISFAILURE=`sudo hcitool cc $ADDRESS 2>&1`
+	
+		if [ -z "$ANYTEXTISFAILURE" ] ; then
+			echo "Pairing successfull"
+			RESULT=0
+		else
+			echo "$ANYTEXTISFAILURE"
+			echo "Pairing failed"
+		fi
+	
+		#echo "Killing pid=$PASSPID"
+		# Kill bg process
+		sudo kill $PASSPID
+	fi
+fi
+
+#
+# A2DP Setting
+#
+echo "Select device for a2dp (y/N)?"
+read A2PARAM
+
+if [ "$A2PARAM" = "y" ] ; then
+	echo "Writing ~/.a2dprc"
+	if [ -f ~/.a2dprc ] ; then
+		mv -f ~/.a2dprc ~/.a2dprc~
+		cat ~/.a2dprc~ | while read LINE ; do
+			# Address line
+			if expr "$LINE" : "address=.*" > /dev/null; then
+				echo "address=$ADDRESS" >> ~/.a2dprc
+			else
+				echo "$LINE" >> ~/.a2dprc
+			fi
+		done
+	else
+		echo "[A2DPD]" > ~/.a2dprc
+		echo "address=$ADDRESS" >> ~/.a2dprc
+	fi
+fi
+
+
+#
+# A2DP Daemon
+#
+echo "Start a2dp daemon (y/N)?"
+read A2DAEMON
+if [ "$A2DAEMON" = "y" ] ; then
+	while killall a2dpd 2> /dev/null ; do
+		echo -n .
+		sleep 1
+	done
+	a2dpd -d +v
+fi
+
+#
+# Ending
+#
+exit 0
+
+############
Index: alsa-plugins/a2dpd.c
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/alsa-plugins/a2dpd.c,v
retrieving revision 1.7
diff -u -r1.7 a2dpd.c
--- alsa-plugins/a2dpd.c	30 Aug 2006 14:43:21 -0000	1.7
+++ alsa-plugins/a2dpd.c	31 Aug 2006 15:58:57 -0000
@@ -37,6 +37,7 @@
 #include <linux/uinput.h>
 
 #include "a2dplib.h"
+#include "alsalib.h"
 #include "a2dpd_protocol.h"
 #include "a2dp_timer.h"
 #include "a2dp_ipc.h"
@@ -51,16 +52,18 @@
 #define UINPUT_DEVICE          "/dev/input/uinput"
 #define A2DPD_CONFIG_FILE       ".a2dpdrc"
 
-
-static char     g_sOutputFilename       [512];
-static char     g_srcfilename           [512];
-static char     g_sCmdPlay              [512];
-static char     g_sCmdPause             [512];
-static char     g_sCmdPrev              [512];
-static char     g_sCmdNext              [512];
-static char     g_sCmdNew               [512];
-static int      g_nbdeviceconnected     = 0;
-static int      uinput_fd               = -1;
+static char g_sOutputFilename[512];
+static char g_srcfilename[512];
+static char g_sCmdPlay[512];
+static char g_sCmdPause[512];
+static char g_sCmdPrev[512];
+static char g_sCmdNext[512];
+static char g_sCmdNew[512];
+static int g_nbdeviceconnected = 0;
+static int uinput_fd = -1;
+static int g_bavrcp = 0;
+static int g_brereadconfig = 0;
+static int g_breversestereo = 0;
 
 // This function is needed to destroy zombies processes
 // On Unix, any forked process which terminate before its parent create a zombie until parent call waitpid()
@@ -69,56 +72,49 @@
 // http://www.erlenstar.demon.co.uk/unix/faq_2.html
 void ignore_child_processes_return_values()
 {
-        struct sigaction sa;
-        sa.sa_handler = SIG_IGN;
-        #ifdef SA_NOCLDWAIT
-        sa.sa_flags = SA_NOCLDWAIT;
-        #else
-        sa.sa_flags = 0;
-        #endif
-        sigemptyset(&sa.sa_mask);
-        sigaction(SIGCHLD, &sa, NULL);
+	struct sigaction sa;
+	sa.sa_handler = SIG_IGN;
+#ifdef SA_NOCLDWAIT
+	sa.sa_flags = SA_NOCLDWAIT;
+#else
+	sa.sa_flags = 0;
+#endif
+	sigemptyset(&sa.sa_mask);
+	sigaction(SIGCHLD, &sa, NULL);
 }
 
-void make_daemon_process(int bFork, int bVerbose, char*output_file_name)
+void make_daemon_process(int bFork, int bVerbose, char *output_file_name)
 {
-        // Fork to background process if needed
-        if (bFork == 1)
-        {
-                switch (fork())
-                {
-                        case -1:
-                                exit(-1);
-                        case 0:
-				break;
-                        default:
-                                exit(0);
-                }
-
-                setsid();
-                chdir("/");
-        }
-
-        // Redirect output to file (default /dev/null) in silent mode, verbose will print output to stdin/out/err
-        if(!bVerbose)
-        {
-                int fd;
-                if ((fd = open(output_file_name, O_CREAT|O_APPEND|O_RDWR, 0)) != -1)
-                {
-                        fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
-                        (void) dup2(fd, STDIN_FILENO);
-                        (void) dup2(fd, STDOUT_FILENO);
-                        (void) dup2(fd, STDERR_FILENO);
-                        if (fd > 2)
-                                (void) close(fd);
-                }
-                else
-                {
-                        printf("a2dpd: Couldn't redirect output to '%s' (errno=%d:%s)", output_file_name, errno, strerror(errno));
-                }
-        }
+	// Fork to background process if needed
+	if (bFork == 1) {
+		switch (fork()) {
+		case -1:
+			exit(-1);
+		case 0:
+			break;
+		default:
+			exit(0);
+		}
 
-        printf("a2dpd [%s %s] starting ...", __DATE__, __TIME__);
+		setsid();
+		chdir("/");
+	}
+	// Redirect output to file (default /dev/null) in silent mode, verbose will print output to stdin/out/err
+	if (!bVerbose) {
+		int fd;
+		if ((fd = open(output_file_name, O_CREAT | O_APPEND | O_RDWR, 0)) != -1) {
+			fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+			(void) dup2(fd, STDIN_FILENO);
+			(void) dup2(fd, STDOUT_FILENO);
+			(void) dup2(fd, STDERR_FILENO);
+			if (fd > 2)
+				(void) close(fd);
+		} else {
+			printf("a2dpd: Couldn't redirect output to '%s' (errno=%d:%s)", output_file_name, errno, strerror(errno));
+		}
+	}
+
+	printf("a2dpd [%s %s] starting ...", __DATE__, __TIME__);
 }
 
 static int lock_fd(int fd)
@@ -141,54 +137,52 @@
 // Prepare packet headers
 static void init_response(struct avctp_header *header)
 {
-        header->ipid = 0;
-        header->cr = AVCTP_RESPONSE_FRAME;
-        header->packet_type = PACKET_TYPE_SINGLE;
+	header->ipid = 0;
+	header->cr = AVCTP_RESPONSE_FRAME;
+	header->packet_type = PACKET_TYPE_SINGLE;
 }
 
 
-static int init_uinput ()
+static int init_uinput()
 {
 	int fd, i;
 	struct uinput_user_dev dev = {
 		.id = {
-			.bustype = BUS_BLUETOOTH,
-			.version = 0x0001,
-		}
+		       .bustype = BUS_BLUETOOTH,
+		       .version = 0x0001,
+		       }
 	};
 
-	if((fd = open(UINPUT_DEVICE, O_WRONLY)) < 0)
-	{
+	if ((fd = open(UINPUT_DEVICE, O_WRONLY)) < 0) {
 		perror("Cannot open " UINPUT_DEVICE);
 		goto shutdown;
 	}
 
-	if(write(fd, &dev, sizeof(dev)) < sizeof(dev))
-	{
+	if (write(fd, &dev, sizeof(dev)) < sizeof(dev)) {
 		perror("Cannot create a uinput device");
 		goto release;
 	}
 
-	if(ioctl(fd, UI_SET_EVBIT, EV_KEY))
+	if (ioctl(fd, UI_SET_EVBIT, EV_KEY))
 		goto release;
 
-	for(i = 0; i <= KEY_MAX; i++)
-		if(ioctl(fd, UI_SET_KEYBIT, i))
+	for (i = 0; i <= KEY_MAX; i++)
+		if (ioctl(fd, UI_SET_KEYBIT, i))
 			goto release;
-	if(ioctl(fd, UI_DEV_CREATE))
+	if (ioctl(fd, UI_DEV_CREATE))
 		goto release;
 
 	uinput_fd = fd;
 
 	return 0;
- release:
+      release:
 	ioctl(fd, UI_DEV_DESTROY);
- shutdown:
+      shutdown:
 	close(fd);
 	return 1;
 }
 
-static void kill_uinput ()
+static void kill_uinput()
 {
 	if (uinput_fd == -1)
 		return;
@@ -197,99 +191,93 @@
 	close(uinput_fd);
 }
 
-static void send_key (unsigned short code)
+static void send_key(unsigned short code)
 {
 	struct input_event ev = {
 		.type = EV_KEY,
 		.code = code,
-		.time = {0, }
+		.time = {0,}
 	};
 
 	if (uinput_fd == -1)
 		return;
 
-	if(code > KEY_MAX)
+	if (code > KEY_MAX)
 		return;
-  
-	ev.value = 1; // press...
+
+	ev.value = 1;		// press...
 	write(uinput_fd, &ev, sizeof(ev));
 
-	ev.value = 0; // then release
+	ev.value = 0;		// then release
 	write(uinput_fd, &ev, sizeof(ev));
 }
 
 // This function handle the bluetooth connection
 int a2dp_handle_avrcp_message(int sockfd)
 {
-        char lpFrame [A2DPMAXIMUMTRANSFERUNITSIZE];
-        int iReceived = recv(sockfd, lpFrame, sizeof(lpFrame), 0);
-        if(iReceived>0)
-        {
-                struct avc_frame frame = *((struct avc_frame*)lpFrame);
-
-                // Handle message
-                if(frame.ctype == CMD_PASSTHROUGH)
-                {
-                        switch (frame.operand0)
-                        {
-                        case PLAY_OP:
-                                printf("[play] %s\n", g_sCmdPlay);
-                                if(g_sCmdPlay[0]) async_run_process(g_sCmdPlay);
-				send_key (KEY_PLAY);
-                                break;
-                        case PAUSE_OP:
-                                printf("[pause] %s\n", g_sCmdPause);
-                                if(g_sCmdPause[0]) async_run_process(g_sCmdPause);
-				send_key (KEY_PAUSE);
-                                break;
-                        case NEXT_OP:
-                                printf("[next] %s\n", g_sCmdNext);
-                                if(g_sCmdNext[0]) async_run_process(g_sCmdNext);
-				send_key (KEY_NEXTSONG);
-                                break;
-                        case PREV_OP:
-                                printf("[previous] %s\n", g_sCmdPrev);
-                                if(g_sCmdPrev[0]) async_run_process(g_sCmdPrev);
-				send_key (KEY_PREVIOUSSONG);
-                                break;
-                        default:
-                                printf("received passthrough %d bytes:\n", iReceived);
-                                //dump_packet(&frame, iReceived);
-                        }
-                }
-                else
-                {
-                        printf("received %d bytes:\n", iReceived);
-                        //dump_packet(&frame, iReceived);
-                }
-                // Send response
-                if(iReceived > 0)
-                {
-                        if(frame.ctype == CMD_ACCEPTED)
-                        {
-                                printf("(ack)\n");
-                        }
-                        else
-                        if(frame.ctype == CMD_PASSTHROUGH)
-                        {
-                                init_response(&frame.header);
-                                frame.ctype = CMD_ACCEPTED;
-                                write(sockfd, &frame, iReceived);
-                        }
-                        else
-                        {
-                                printf("only passthrough ctype command is implemented. doh!\n");
-                                // ierk!!! exit(0);
-                        }
-                }
-        }
-        else
-        {
-                if(errno!=EAGAIN)
-                        printf("socket %d: Receive failed %d (error %d:%s)\n", sockfd, iReceived, errno, strerror(errno));
-        }
+	char lpFrame[A2DPMAXIMUMTRANSFERUNITSIZE];
+	int iReceived = recv(sockfd, lpFrame, sizeof(lpFrame), 0);
+	if (iReceived > 0) {
+		struct avc_frame frame = *((struct avc_frame *) lpFrame);
+
+		// Handle message
+		if (frame.ctype == CMD_PASSTHROUGH) {
+			switch (frame.operand0) {
+			case PLAY_OP:
+				printf("[play] %s\n", g_sCmdPlay);
+				if (g_sCmdPlay[0])
+					async_run_process(g_sCmdPlay);
+				else
+					send_key(KEY_PLAY);
+				break;
+			case PAUSE_OP:
+				printf("[pause] %s\n", g_sCmdPause);
+				if (g_sCmdPause[0])
+					async_run_process(g_sCmdPause);
+				else
+					send_key(KEY_PAUSE);
+				break;
+			case NEXT_OP:
+				printf("[next] %s\n", g_sCmdNext);
+				if (g_sCmdNext[0])
+					async_run_process(g_sCmdNext);
+				else
+					send_key(KEY_NEXTSONG);
+				break;
+			case PREV_OP:
+				printf("[previous] %s\n", g_sCmdPrev);
+				if (g_sCmdPrev[0])
+					async_run_process(g_sCmdPrev);
+				else
+					send_key(KEY_PREVIOUSSONG);
+				break;
+			default:
+				printf("received passthrough %d bytes:\n", iReceived);
+				//dump_packet(&frame, iReceived);
+			}
+		} else {
+			printf("received %d bytes:\n", iReceived);
+			//dump_packet(&frame, iReceived);
+		}
+		// Send response
+		if (iReceived > 0) {
+			if (frame.ctype == CMD_ACCEPTED) {
+				printf("(ack)\n");
+			} else if (frame.ctype == CMD_PASSTHROUGH) {
+				init_response(&frame.header);
+				frame.ctype = CMD_ACCEPTED;
+				write(sockfd, &frame, iReceived);
+			} else {
+				printf("only passthrough ctype command is implemented. doh!\n");
+				// ierk!!! exit(0);
+			}
+		}
+	} else {
+		if (errno != EAGAIN)
+			printf("socket %d: Receive failed %d (error %d:%s)\n", sockfd, iReceived, errno, strerror(errno));
+	}
 
-        return iReceived;
+	return iReceived;
 }
 
 //////////////////////////////////////////
@@ -306,738 +294,709 @@
 
 #define max(x,y) ((x)>(y)?(x):(y))
 
-char* pool_pop()
+char *pool_pop()
 {
-        return malloc(POOLENTRYSIZE);
+	return malloc(POOLENTRYSIZE);
 }
 
-void pool_push(char* pool)
+void pool_push(char *pool)
 {
-        free(pool);
+	free(pool);
 }
 
 // Data used to mix audio
-typedef struct
-{
-        int                     lives;
-        pthread_mutex_t         mutex;
-        int                     ring_in;
-        int                     ring_out;
-        int                     ring_len[MAXCLIENTSRINGSIZE];
-        char*                   ring[MAXCLIENTSRINGSIZE];
+typedef struct {
+	int lives;
+	pthread_mutex_t mutex;
+	int ring_in;
+	int ring_out;
+	int ring_len[MAXCLIENTSRINGSIZE];
+	char *ring[MAXCLIENTSRINGSIZE];
 } BTA2DPPERCLIENTDATA;
 
 // Data to keep per Bluetooth device
-typedef struct
-{
-        char                    addr[20];
-        pthread_t               thread;
-        pthread_t               receiverthread;
-        pthread_mutex_t         mutex;
-        AUDIOMIXERDATA          mixer;
-        int                     nb_clients;
-        BTA2DPPERCLIENTDATA     clients[MAXCLIENTSPERDEVICE];
+typedef struct {
+	char addr[20];
+	char plug[20];
+	pthread_t thread;
+	pthread_t receiverthread;
+	pthread_mutex_t mutex;
+	AUDIOMIXERDATA mixer;
+	int nb_clients;
+	int bredirectalsa;
+	BTA2DPPERCLIENTDATA clients[MAXCLIENTSPERDEVICE];
 } BTA2DPPERDEVICEDATA, *LPBTA2DPPERDEVICEDATA;
 
 // Data needed per Audio Streaming Client
-typedef struct
-{
-        LPBTA2DPPERDEVICEDATA   lpDevice;
-        int                     sockfd;
-        pthread_t               thread;
+typedef struct {
+	LPBTA2DPPERDEVICEDATA lpDevice;
+	int sockfd;
+	pthread_t thread;
 } A2DPDCLIENT, *LPA2DPDCLIENT;
 
 // Allocate a new device
-LPBTA2DPPERDEVICEDATA bta2dpdevicenew(char* addr)
+LPBTA2DPPERDEVICEDATA bta2dpdevicenew(char *addr)
 {
-        int i = 0;
-        LPBTA2DPPERDEVICEDATA lpDevice = malloc(sizeof(BTA2DPPERDEVICEDATA));
-        if(lpDevice)
-        {
-                memset(lpDevice, 0, sizeof(BTA2DPPERDEVICEDATA));
-                strncpy(lpDevice->addr, addr, sizeof(lpDevice->addr)); lpDevice->addr[sizeof(lpDevice->addr)-1] = 0;
-                lpDevice->mixer.volume_speaker_left = A2DPD_VOLUME_MAX;
-                lpDevice->mixer.volume_speaker_right = A2DPD_VOLUME_MAX;
-                lpDevice->mixer.volume_micro_left = A2DPD_VOLUME_MAX;
-                lpDevice->mixer.volume_micro_right = A2DPD_VOLUME_MAX;
-                pthread_mutex_init(&lpDevice->mutex, NULL);
-                for(i=0;i<MAXCLIENTSPERDEVICE; i++)
-                {
-                        pthread_mutex_init(&lpDevice->clients[i].mutex, NULL);
-                }
-        }
-        return lpDevice;
+	int i = 0;
+	LPBTA2DPPERDEVICEDATA lpDevice = malloc(sizeof(BTA2DPPERDEVICEDATA));
+	if (lpDevice) {
+		memset(lpDevice, 0, sizeof(BTA2DPPERDEVICEDATA));
+		strncpy(lpDevice->addr, addr, sizeof(lpDevice->addr));
+		lpDevice->addr[sizeof(lpDevice->addr) - 1] = 0;
+		lpDevice->mixer.volume_speaker_left = A2DPD_VOLUME_MAX;
+		lpDevice->mixer.volume_speaker_right = A2DPD_VOLUME_MAX;
+		lpDevice->mixer.volume_micro_left = A2DPD_VOLUME_MAX;
+		lpDevice->mixer.volume_micro_right = A2DPD_VOLUME_MAX;
+		pthread_mutex_init(&lpDevice->mutex, NULL);
+		for (i = 0; i < MAXCLIENTSPERDEVICE; i++) {
+			pthread_mutex_init(&lpDevice->clients[i].mutex, NULL);
+		}
+	}
+	return lpDevice;
 }
 
 // Free a device
 void bta2dpdevicefree(LPBTA2DPPERDEVICEDATA lpDevice)
 {
-        int i = 0;
-        if(lpDevice)
-        {
-                for(i=0;i<MAXCLIENTSPERDEVICE; i++)
-                {
-                        pthread_mutex_destroy(&lpDevice->clients[i].mutex);
-                }
-                pthread_mutex_destroy(&lpDevice->mutex);
-                free(lpDevice);
-        }
+	int i = 0;
+	if (lpDevice) {
+		for (i = 0; i < MAXCLIENTSPERDEVICE; i++) {
+			pthread_mutex_destroy(&lpDevice->clients[i].mutex);
+		}
+		pthread_mutex_destroy(&lpDevice->mutex);
+		free(lpDevice);
+	}
 }
 
 // handle sigterm to terminate properly
 void sigint_handler(int sig)
 {
-        // User wants to force quit
-        if(bSigINTReceived==1) 
-        {
-                printf("handling SIGINT again: exit forced\n");
-                exit(0);
-        }
-        else
-        {
-                // Now we must quit properly
-                bSigINTReceived = 1;
-                printf("handling SIGINT\n");
-        
-                // Dummy connection to unlock server (currently accepting)
-                close_socket(make_client_socket());
-        }
+	// User wants to force quit
+	if (bSigINTReceived == 1) {
+		printf("handling SIGINT again: exit forced\n");
+		exit(0);
+	} else {
+		// Now we must quit properly
+		bSigINTReceived = 1;
+		printf("handling SIGINT\n");
+
+		// Dummy connection to unlock server (currently accepting)
+		close_socket(make_client_socket());
+	}
 }
 
 // This function handles a client
-void* client_handler(void* param)
+void *client_handler(void *param)
 {
-        int bError = 0;
-        int client_index = -1;
-        int32_t client_type = INVALID_CLIENT_TYPE;
-        int result;
-        LPA2DPDCLIENT lpClient = (LPA2DPDCLIENT)param;
-        AUDIOMIXERDATA AudioMixerData = INVALIDAUDIOMIXERDATA;
-
-        // We should not terminate the process if clients are still running
-        iThreadsRunning ++;
-
-        pthread_detach(lpClient->thread);
-
-        setup_socket(lpClient->sockfd);
-
-        // Receive type of client
-        result = recv_socket(lpClient->sockfd, &client_type, sizeof(client_type));
-
-        // This client wants to send us pcm control data
-        if(client_type==A2DPD_PLUGIN_CTL_WRITE)
-        {
-                printf("CTL WRITE thread %d.%d started\n", client_index, lpClient->sockfd);
-
-                if(recv_socket(lpClient->sockfd, &AudioMixerData, sizeof(AudioMixerData))==sizeof(AudioMixerData))
-                {
-                        pthread_mutex_lock(&lpClient->lpDevice->mutex);
-                        if(AudioMixerData.volume_speaker_left != -1)
-                                lpClient->lpDevice->mixer.volume_speaker_left = AudioMixerData.volume_speaker_left;
-                        if(AudioMixerData.volume_speaker_left != -1)
-                                lpClient->lpDevice->mixer.volume_speaker_right= AudioMixerData.volume_speaker_right;
-                        if(AudioMixerData.volume_micro_left != -1)
-                                lpClient->lpDevice->mixer.volume_micro_left = AudioMixerData.volume_micro_left;
-                        if(AudioMixerData.volume_micro_left != -1)
-                                lpClient->lpDevice->mixer.volume_micro_right= AudioMixerData.volume_micro_right;
-                        pthread_mutex_unlock(&lpClient->lpDevice->mutex);
-                        // Notify other clients
-                        int notifyfd = make_udp_socket();
-                        int i=send_socket(notifyfd, &AudioMixerData, sizeof(AudioMixerData));
-                        printf("Notify return %d\n", i);
-                        close_socket(notifyfd);
-                }
-        }
-
-        // This client wants to read our control status
-        if(client_type==A2DPD_PLUGIN_CTL_READ)
-        {
-                printf("CTL READ thread %d.%d started\n", client_index, lpClient->sockfd);
-
-                pthread_mutex_lock(&lpClient->lpDevice->mutex);
-                AudioMixerData = lpClient->lpDevice->mixer;
-                pthread_mutex_unlock(&lpClient->lpDevice->mutex);
-
-                send_socket(lpClient->sockfd, &AudioMixerData, sizeof(AudioMixerData));
-        }
-
-        // This client wants to send us pcm stream
-        if(client_type==A2DPD_PLUGIN_PCM_WRITE)
-        {
-                // Find an index in clients table for the mixer
-                pthread_mutex_lock(&lpClient->lpDevice->mutex);
-                for(client_index=0; client_index<MAXCLIENTSPERDEVICE; client_index++)
-                {
-                        if(lpClient->lpDevice->clients[client_index].lives==0)
-                        {
-                                lpClient->lpDevice->clients[client_index].lives = 1;
-                                lpClient->lpDevice->clients[client_index].ring_in = 0;
-                                lpClient->lpDevice->clients[client_index].ring_out = 0;
-                                break;
-                        }
-                }
-                pthread_mutex_unlock(&lpClient->lpDevice->mutex);
-
-                printf("PCM thread %d.%d started\n", client_index, lpClient->sockfd);
-
-                if(client_index>=MAXCLIENTSPERDEVICE)
-                {
-                        printf("Client thread %d cannot start (too many clients already connected)\n", client_index);
-                        return 0;
-                }
-
-                // Loop while we receive data
-                while(!bSigINTReceived && !bError)
-                {
-                        // Receive data
-                        int32_t pcm_buffer_size = 0;
-                        result = recv_socket(lpClient->sockfd, &pcm_buffer_size, sizeof(pcm_buffer_size));
-                        if(result == sizeof(pcm_buffer_size) && pcm_buffer_size<=POOLENTRYSIZE)
-                        {
-                                char* pcm_buffer = pool_pop();
-                                result = recv_socket(lpClient->sockfd, pcm_buffer, pcm_buffer_size);
-
-                                if(result==pcm_buffer_size)
-                                {
-                                        // Enqueue in bluetooth headset if we can else loose packet
-                                        pthread_mutex_lock(&lpClient->lpDevice->clients[client_index].mutex);
-
-                                        // Append data to ring
-                                        int this_ring = lpClient->lpDevice->clients[client_index].ring_in;
-                                        int next_ring = ((this_ring+1)%MAXCLIENTSRINGSIZE);
-
-                                        if(next_ring != lpClient->lpDevice->clients[client_index].ring_out)
-                                        {
-                                                lpClient->lpDevice->clients[client_index].ring[this_ring] = pcm_buffer;
-                                                lpClient->lpDevice->clients[client_index].ring_len[this_ring] = pcm_buffer_size;
-                                                lpClient->lpDevice->clients[client_index].ring_in = next_ring;
-                                                // We will not free that buffer, it's the bthandler thread which will do it
-                                                pcm_buffer = NULL;
-                                        }
-
-                                        pthread_mutex_unlock(&lpClient->lpDevice->clients[client_index].mutex);
-
-                                        // Reintegrate data in pool
-                                        if(pcm_buffer) pool_push(pcm_buffer);
-                                }
-                                else
-                                {
-                                        printf("[2] Receiving failed on socket %d.%d error (%d/%d bytes)\n", client_index, lpClient->sockfd, result, pcm_buffer_size);
-                                        bError = 1;
-                                }
-                        }
-                        else
-                        {
-                                if(result==sizeof(pcm_buffer_size))
-                                {
-                                        printf("[1] Receiving will not fit pool (poolentrysize=%d != pcm_buffer_size=%d)\n", POOLENTRYSIZE, pcm_buffer_size);
-                                }
-                                else
-                                {
-                                        printf("[1] Receiving failed on socket %d.%d error (%d/%d bytes) errno=%d:%s\n", client_index, lpClient->sockfd, result, sizeof(pcm_buffer_size), errno, strerror(errno));
-                                }
-                                bError = 1;
-                        }
-                }
-
-                pthread_mutex_lock(&lpClient->lpDevice->mutex);
-                if(client_index>=0) lpClient->lpDevice->clients[client_index].lives=0;
-                pthread_mutex_unlock(&lpClient->lpDevice->mutex);
-        }
-
-        // Say goodbye
-        pthread_mutex_lock(&lpClient->lpDevice->mutex);
-        lpClient->lpDevice->nb_clients--;
-        pthread_mutex_unlock(&lpClient->lpDevice->mutex);
-
-        // Close socket
-        printf("Client thread %d.%d ending: %s\n", client_index, lpClient->sockfd, (bError?(errno==EAGAIN?"timeout":"error"):"no error"));
-        close_socket(lpClient->sockfd);
+	int bError = 0;
+	int client_index = -1;
+	int32_t client_type = INVALID_CLIENT_TYPE;
+	int result;
+	LPA2DPDCLIENT lpClient = (LPA2DPDCLIENT) param;
+	AUDIOMIXERDATA AudioMixerData = INVALIDAUDIOMIXERDATA;
+
+	// We should not terminate the process if clients are still running
+	iThreadsRunning++;
+
+	pthread_detach(lpClient->thread);
+
+	setup_socket(lpClient->sockfd);
+
+	// Receive type of client
+	result = recv_socket(lpClient->sockfd, &client_type, sizeof(client_type));
+
+	// This client wants to send us pcm control data
+	if (client_type == A2DPD_PLUGIN_CTL_WRITE) {
+		printf("CTL WRITE thread %d.%d started\n", client_index, lpClient->sockfd);
+
+		if (recv_socket(lpClient->sockfd, &AudioMixerData, sizeof(AudioMixerData)) == sizeof(AudioMixerData)) {
+			pthread_mutex_lock(&lpClient->lpDevice->mutex);
+			if (AudioMixerData.volume_speaker_left != -1)
+				lpClient->lpDevice->mixer.volume_speaker_left = AudioMixerData.volume_speaker_left;
+			if (AudioMixerData.volume_speaker_left != -1)
+				lpClient->lpDevice->mixer.volume_speaker_right = AudioMixerData.volume_speaker_right;
+			if (AudioMixerData.volume_micro_left != -1)
+				lpClient->lpDevice->mixer.volume_micro_left = AudioMixerData.volume_micro_left;
+			if (AudioMixerData.volume_micro_left != -1)
+				lpClient->lpDevice->mixer.volume_micro_right = AudioMixerData.volume_micro_right;
+			pthread_mutex_unlock(&lpClient->lpDevice->mutex);
+			// Notify other clients
+			int notifyfd = make_udp_socket();
+			int i = send_socket(notifyfd, &AudioMixerData,
+					    sizeof(AudioMixerData));
+			printf("Notify return %d\n", i);
+			close_socket(notifyfd);
+		}
+	}
+	// This client wants to read our control status
+	if (client_type == A2DPD_PLUGIN_CTL_READ) {
+		printf("CTL READ thread %d.%d started\n", client_index, lpClient->sockfd);
+
+		pthread_mutex_lock(&lpClient->lpDevice->mutex);
+		AudioMixerData = lpClient->lpDevice->mixer;
+		pthread_mutex_unlock(&lpClient->lpDevice->mutex);
+
+		send_socket(lpClient->sockfd, &AudioMixerData, sizeof(AudioMixerData));
+	}
+	// This client wants to send us pcm stream
+	if (client_type == A2DPD_PLUGIN_PCM_WRITE) {
+		// Find an index in clients table for the mixer
+		pthread_mutex_lock(&lpClient->lpDevice->mutex);
+		for (client_index = 0; client_index < MAXCLIENTSPERDEVICE; client_index++) {
+			if (lpClient->lpDevice->clients[client_index].lives == 0) {
+				lpClient->lpDevice->clients[client_index].lives = 1;
+				lpClient->lpDevice->clients[client_index].ring_in = 0;
+				lpClient->lpDevice->clients[client_index].ring_out = 0;
+				break;
+			}
+		}
+		pthread_mutex_unlock(&lpClient->lpDevice->mutex);
+
+		printf("PCM thread %d.%d started\n", client_index, lpClient->sockfd);
+
+		if (client_index >= MAXCLIENTSPERDEVICE) {
+			printf("Client thread %d cannot start (too many clients already connected)\n", client_index);
+			return 0;
+		}
+		// Loop while we receive data
+		while (!bSigINTReceived && !bError) {
+			// Receive data
+			int32_t pcm_buffer_size = 0;
+			result = recv_socket(lpClient->sockfd, &pcm_buffer_size, sizeof(pcm_buffer_size));
+			if (result == sizeof(pcm_buffer_size)
+			    && pcm_buffer_size <= POOLENTRYSIZE) {
+				char *pcm_buffer = pool_pop();
+				result = recv_socket(lpClient->sockfd, pcm_buffer, pcm_buffer_size);
+
+				if (result == pcm_buffer_size) {
+					// Enqueue in bluetooth headset if we can else loose packet
+					pthread_mutex_lock(&lpClient->lpDevice->clients[client_index].mutex);
+
+					// Append data to ring
+					int this_ring = lpClient->lpDevice->clients[client_index].ring_in;
+					int next_ring = ((this_ring + 1) % MAXCLIENTSRINGSIZE);
+
+					if (next_ring != lpClient->lpDevice->clients[client_index].ring_out) {
+						lpClient->lpDevice->clients[client_index].ring[this_ring] = pcm_buffer;
+						lpClient->lpDevice->clients[client_index].ring_len[this_ring] = pcm_buffer_size;
+						lpClient->lpDevice->clients[client_index].ring_in = next_ring;
+						// We will not free that buffer, it's the bthandler thread which will do it
+						pcm_buffer = NULL;
+					}
+
+					pthread_mutex_unlock(&lpClient->lpDevice->clients[client_index].mutex);
+
+					// Reintegrate data in pool
+					if (pcm_buffer)
+						pool_push(pcm_buffer);
+				} else {
+					printf("[2] Receiving failed on socket %d.%d error (%d/%d bytes)\n", client_index, lpClient->sockfd, result, pcm_buffer_size);
+					bError = 1;
+				}
+			} else {
+				if (result == sizeof(pcm_buffer_size)) {
+					printf("[1] Receiving will not fit pool (poolentrysize=%d != pcm_buffer_size=%d)\n", POOLENTRYSIZE, pcm_buffer_size);
+				} else {
+					printf("[1] Receiving failed on socket %d.%d error (%d/%d bytes) errno=%d:%s\n", client_index, lpClient->sockfd, result, sizeof(pcm_buffer_size), errno,
+					       strerror(errno));
+				}
+				bError = 1;
+			}
+		}
+
+		pthread_mutex_lock(&lpClient->lpDevice->mutex);
+		if (client_index >= 0)
+			lpClient->lpDevice->clients[client_index].lives = 0;
+		pthread_mutex_unlock(&lpClient->lpDevice->mutex);
+	}
+	// Say goodbye
+	pthread_mutex_lock(&lpClient->lpDevice->mutex);
+	lpClient->lpDevice->nb_clients--;
+	pthread_mutex_unlock(&lpClient->lpDevice->mutex);
+
+	// Close socket
+	printf("Client thread %d.%d ending: %s\n", client_index, lpClient->sockfd, (bError ? (errno == EAGAIN ? "timeout" : "error") : "no error"));
+	close_socket(lpClient->sockfd);
+
+	// Free client data
+	free(lpClient);
+
+	// Decrease thread count
+	iThreadsRunning--;
 
-        // Free client data
-        free(lpClient);
+	return 0;
+}
 
-        // Decrease thread count
-        iThreadsRunning --;
+/////////////////////////////////
+int audio_mixer(void *pcm_buffer, char **pcm_buffers, int *pcm_buffers_size, int vol_left, int vol_right)
+/////////////////////////////////
+{
+	int i, j;
+	int satured = 0;
+
+	// Mix audio streams 16 bits stereo channels
+	// We require little endianness here
+	int pcm_buffer_filed_size = 0;
+	for (j = 0; j < POOLENTRYSIZE / 4; j++) {
+		int32_t *pBuffer = (int32_t *) pcm_buffer;
+		int32_t channel_1 = 0;
+		int32_t channel_2 = 0;
+		for (i = 0; i < MAXCLIENTSPERDEVICE; i++) {
+			int32_t *pBuffers = (int32_t *) (pcm_buffers[i]);
+			if (pBuffers != NULL && (j < pcm_buffers_size[i] / 4)) {
+				int16_t i1 = *(((int16_t *) (pBuffers + j)) + 0);
+				int16_t i2 = *(((int16_t *) (pBuffers + j)) + 1);
+				channel_1 += i1;
+				channel_2 += i2;
+				pcm_buffer_filed_size = max(pcm_buffer_filed_size, pcm_buffers_size[i]);
+			}
+		}
+		//printf("Value %08X|%08X %d|%d\n", channel_1, channel_2, channel_1, channel_2);
+		// Stay within 16 bits per channel range
+		if (channel_1 > +32767) {
+			channel_1 = +32767;
+			satured++;
+		}
+		if (channel_1 < -32768) {
+			channel_1 = -32768;
+			satured++;
+		}
+		if (channel_2 > +32767) {
+			channel_2 = +32767;
+			satured++;
+		}
+		if (channel_2 < -32768) {
+			channel_2 = -32768;
+			satured++;
+		}
 
-        return 0;
+		channel_1 *= vol_left;
+		channel_2 *= vol_right;
+		// yes this can be rewritten with << if we consider max volume of 2^x
+		// Isn't it already done by compiler?
+		channel_1 /= A2DPD_VOLUME_MAX;
+		channel_2 /= A2DPD_VOLUME_MAX;
+		if(g_breversestereo) {
+			pBuffer[j] = (((channel_1 & 0x0000FFFF) << 16) | (channel_2 & 0x0000FFFF));
+		} else {
+			//FIXME We have a reverse stereo I don't know why
+			// The following line corrects the problem but I miss the cause so
+			pBuffer[j] = (((channel_2&0x0000FFFF)<<16)|(channel_1&0x0000FFFF));
+			pBuffer[j] = ( (channel_1 & 0xFFFF0000) | (channel_2 & 0x0000FFFF) );
+		}
+	}
+	return pcm_buffer_filed_size;
 }
 
 // This function handle the bluetooth connection
-void* bt_handler(void* param)
+void *bt_handler(void *param)
 {
-        int i,j;
-        // We should not terminate the process if clients are still running
-        iThreadsRunning ++;
-
-        LPBTA2DPPERDEVICEDATA lpDevice = (LPBTA2DPPERDEVICEDATA)param;
-        pthread_detach(lpDevice->thread);
-
-        // As long as daemon is running
-        while(!bSigINTReceived)
-        {
-                int bError = 0;
-                int destroy_count = 0;
-                int satured = 0;
-                int ibytespersecond = 0;
-
-                // Connect to the A2DP device
-                LPA2DP lpA2dp = NULL;
-                char* pcm_buffer = pool_pop();
-                enum { NOSOUND, SOUND };
-                int state_previous = NOSOUND;
-                TIMERINFO TimerInfos;
-                int rate = read_config_int(g_srcfilename, "a2dpd", "rate", A2DPD_FRAME_RATE);
-                memset(&TimerInfos, 0, sizeof(TimerInfos));
-                TimerInfos.fps = (float)((((float)rate)*((float)A2DPD_FRAME_BYTES)/((float)A2DPD_BLOCK_SIZE))/1.0);
-                printf("New connection to bluetooth [%d hz]\n", rate);
-
-                // As long as we can send sound
-                while(!bSigINTReceived && !bError)
-                {
-                        int pcm_buffer_filed_size = 0;
-                        char* pcm_buffers[MAXCLIENTSPERDEVICE];
-                        int pcm_buffers_size[MAXCLIENTSPERDEVICE];
-                        int state_current = NOSOUND;
-                        memset(pcm_buffers,      0, sizeof(pcm_buffers));
-                        memset(pcm_buffers_size, 0, sizeof(pcm_buffers_size));
-
-                        // If there are BT data, send them
-                        //FIXME Since we read nb_clients, we should lock mutex, but it may create timer issues
-                        // pthread_mutex_lock(&lpDevice->mutex);
-
-                        if(lpDevice->nb_clients>0)
-                        {
-                                // Retrieve data for client where it is available
-                                for(i=0; i<MAXCLIENTSPERDEVICE; i++)
-                                {
-                                        if(lpDevice->clients[i].lives)
-                                        {
-                                                pthread_mutex_lock(&lpDevice->clients[i].mutex);
-                                
-                                                if(lpDevice->clients[i].ring_in != lpDevice->clients[i].ring_out)
-                                                {
-                                                        // Get ring buffer
-                                                        pcm_buffers[i] = lpDevice->clients[i].ring[lpDevice->clients[i].ring_out];
-                                                        pcm_buffers_size[i] = lpDevice->clients[i].ring_len[lpDevice->clients[i].ring_out];
-                                                        // Tell client we got them
-                                                        lpDevice->clients[i].ring[lpDevice->clients[i].ring_out] = NULL;
-                                                        lpDevice->clients[i].ring_len[lpDevice->clients[i].ring_out] = 0;
-
-                                                        // Move to next ring
-                                                        int next_ring = ((lpDevice->clients[i].ring_out+1)%MAXCLIENTSRINGSIZE);
-                                                        
-                                                        //printf("Reading pool %d[ %d] = %p\n", i, lpDevice->clients[i].ring_out, pcm_buffers[i]);
-                                                        
-                                                        lpDevice->clients[i].ring_out = next_ring;
-                                                        
-                                                        // Remember we got some sound
-                                                        state_current = SOUND;
-                                                }
-                                                
-                                                pthread_mutex_unlock(&lpDevice->clients[i].mutex);
-                                        }
-                                }
-                        }
-                        //FIXME 
-                        // pthread_mutex_unlock(&lpDevice->mutex);
-
-                        // Send mixed audio stream to clients
-                        switch(state_current)
-                        {
-                                case SOUND:
-                                {
-                                        /////////////////////////////////
-                                        // Mix what we got
-                                        /////////////////////////////////
-
-                                        static int frames = 0;
-                                        frames ++;
-                                        
-                                        // Mix audio streams 16 bits stereo channels
-                                        // We require little endianness here
-                                        pcm_buffer_filed_size = 0;
-                                        for(j=0; j<POOLENTRYSIZE/4; j++)
-                                        {
-                                                int32_t* pBuffer = (int32_t*)pcm_buffer;
-                                                int32_t channel_1 = 0;
-                                                int32_t channel_2 = 0;
-                                                for(i=0; i<MAXCLIENTSPERDEVICE; i++)
-                                                {
-                                                        int32_t* pBuffers = (int32_t*)(pcm_buffers[i]);
-                                                        if(pBuffers != NULL && (j<pcm_buffers_size[i]/4))
-                                                        {
-                                                                int16_t i1 = *(((int16_t*)(pBuffers+j))+0);
-                                                                int16_t i2 = *(((int16_t*)(pBuffers+j))+1);
-                                                                channel_1 += i1;
-                                                                channel_2 += i2;
-                                                                pcm_buffer_filed_size = max(pcm_buffer_filed_size, pcm_buffers_size[i]);
-                                                        }
-                                                }
-                                                //printf("Value %08X|%08X %d|%d\n", channel_1, channel_2, channel_1, channel_2);
-                                                // Stay within 16 bits per channel range
-                                                if(channel_1>+32767) { channel_1 = +32767; satured++; }
-                                                if(channel_1<-32768) { channel_1 = -32768; satured++; }
-                                                if(channel_2>+32767) { channel_2 = +32767; satured++; }
-                                                if(channel_2<-32768) { channel_2 = -32768; satured++; }
-                                                
-                                                channel_1 *= lpDevice->mixer.volume_speaker_left;
-                                                channel_2 *= lpDevice->mixer.volume_speaker_right;
-                                                // yes this can be rewritten with << if we consider max volume of 2^x
-                                                // Isn't it already done by compiler
-                                                channel_1 /= A2DPD_VOLUME_MAX;
-                                                channel_2 /= A2DPD_VOLUME_MAX;
-                                                pBuffer[j] = (((channel_1&0x0000FFFF)<<16)|(channel_2&0x0000FFFF));
-                                                //FIXME We have a reverse stereo I don't know why
-                                                // The following line corrects the problem but I miss the cause so
-                                                // Do not uncomment it
-                                                //pBuffer[j] = (((channel_2&0x0000FFFF)<<16)|(channel_1&0x0000FFFF));
-                                                //pBuffer[j] = ( (channel_1 & 0xFFFF0000) | (channel_2 & 0x0000FFFF) );
-                                        }
-
-                                        // Free no longer used audio blocks
-                                        for(i=0; i<MAXCLIENTSPERDEVICE; i++)
-                                        {
-                                                if(pcm_buffers[i])
-                                                {
-                                                        // Reintegrate data where they come from
-                                                        pool_push(pcm_buffers[i]);
-                                                }
-                                        }
-
-                                        /////////////////////////////////
-                                        // Transfer data to bluetooth
-                                        /////////////////////////////////
-
-                                        if(pcm_buffer && pcm_buffer_filed_size>0)
-                                        {
-                                                // Transfer takes place by A2DPD_BLOCK_SIZE bytes blocks
-                                                int blockstart = 0;
-                                                int blocksize = A2DPD_BLOCK_SIZE;
-
-                                                // Allocate A2DP if we are not connected
-                                                if(!lpA2dp)
-                                                {
-                                                        lpA2dp = a2dp_new(lpDevice->addr, rate);
-                                                        g_nbdeviceconnected++;
-                                                        destroy_count = 0;
-                                                }
-
-                                                if(lpA2dp)
-                                                {
-                                                        // Send data to BT headset
-                                                        while(!bError && blockstart<pcm_buffer_filed_size)
-                                                        {
-                                                                int transfer;
-
-                                                                blocksize = (pcm_buffer_filed_size<A2DPD_BLOCK_SIZE)?pcm_buffer_filed_size:A2DPD_BLOCK_SIZE;
-
-                                                                transfer = a2dp_transfer_raw(lpA2dp, pcm_buffer+blockstart, blocksize);
-
-                                                                if(transfer>=0)
-                                                                {
-                                                                        destroy_count = 0;
-                                                                        blockstart += blocksize;
-                                                                        ibytespersecond += transfer;
-                                                                        a2dp_timer_notifyframe(&TimerInfos);
-                                                                }
-                                                                else
-                                                                {
-                                                                        printf("Error in a2dp_transfer_raw\n");
-                                                                        bError = 1;
-                                                                }
-                                                        }
-                                                }
-                                        }
-                                        break;
-                                }
-                                case NOSOUND:
-                                {
-                                        if(state_previous == SOUND)
-                                        {
-                                                //printf("Sound stream ran dry!!!\n");
-                                        }
-                                        break;
-                                }
-                        }
-
-                        // Free the A2DP device if needed
-                        // When destroy_count reaches 2000 we will destroy the A2DP link
-                        // However, destroy_count is reset whenever data are sent
-                        destroy_count++;
-                        if(lpA2dp && destroy_count>2000)
-                        {
-                                printf("Destroying lpA2dp, destroy_count is %d\n", destroy_count);
-                                g_nbdeviceconnected--;
-                                a2dp_destroy(lpA2dp);
-                                lpA2dp = NULL;
-                        }
-
-                        // Wait must take place after sending a packet
-                        // This way, you will allow the plugin to send it's data
-                        // And you will collect the new data
-                        // Time reference floating because of 44100/1000 error in integer calculation
-                        a2dp_timer_sleep(&TimerInfos, A2DPTIMERPREDELAY);
-
-                        // Display infos each second
-                        if(TimerInfos.display>0)
-                        {
-                                /*
-                                char* lpszFormat = "A2DPD: [%d,%d|%d,%d] %s %s clients=%d freq=%d[%d b/s] sleep=%d satur=%d\n";
-                                if(satured==0) lpszFormat = "A2DPD: [%d,%d|%d,%d] %s %s clients=%d freq=%d[%d b/s]\n";
-                                printf(lpszFormat, 
-                                lpDevice->mixer.volume_speaker_left,
-                                lpDevice->mixer.volume_speaker_right,
-                                lpDevice->mixer.volume_micro_left,
-                                lpDevice->mixer.volume_micro_right,
-                                (state_current==SOUND)?"playing":"silent",
-                                lpA2dp?"connected":"disconnected", lpDevice->nb_clients, TimerInfos.display,
-                                ibytespersecond,
-                                satured);
-                                // Reset all variables used
-                                ibytespersecond=0;
-                                satured=0;
-                                */
-                        }
-
-                        state_previous = state_current;
-                }
-                pool_push(pcm_buffer);
-
-                // Sleep a little bit before retrying
-                if(!bSigINTReceived)
-                        sleep(1);
-
-                // Free A2DP
-                if(lpA2dp)
-                {
-                        printf("Destroying lpA2dp, end of loop\n");
-                        g_nbdeviceconnected--;
-                        a2dp_destroy(lpA2dp);
-                        lpA2dp = NULL;
-                }
-        }
+	int i;
+	// We should not terminate the process if clients are still running
+	iThreadsRunning++;
+
+	LPBTA2DPPERDEVICEDATA lpDevice = (LPBTA2DPPERDEVICEDATA) param;
+	pthread_detach(lpDevice->thread);
+
+	// As long as daemon is running
+	while (!bSigINTReceived) {
+		int bError = 0;
+		int destroy_count = 0;
+		int ibytespersecond = 0;
+
+		// Connect to the A2DP device
+		void *lpA2dp = NULL;
+		char *pcm_buffer = pool_pop();
+		enum { NOSOUND, SOUND };
+		int state_previous = NOSOUND;
+		TIMERINFO TimerInfos;
+		int rate = read_config_int(g_srcfilename, "a2dpd", "rate",
+					   A2DPD_FRAME_RATE);
+		memset(&TimerInfos, 0, sizeof(TimerInfos));
+		TimerInfos.fps = (float) ((((float) rate) * ((float) A2DPD_FRAME_BYTES) / ((float) A2DPD_BLOCK_SIZE)) / 1.0);
+		printf("New connection to bluetooth [%d hz]\n", rate);
+
+		// As long as we can send sound
+		while (!bSigINTReceived && !bError) {
+			int pcm_buffer_filed_size = 0;
+			char *pcm_buffers[MAXCLIENTSPERDEVICE];
+			int pcm_buffers_size[MAXCLIENTSPERDEVICE];
+			int state_current = NOSOUND;
+			memset(pcm_buffers, 0, sizeof(pcm_buffers));
+			memset(pcm_buffers_size, 0, sizeof(pcm_buffers_size));
+
+			// If there are BT data, send them
+			//FIXME Since we read nb_clients, we should lock mutex, but it may create timer issues
+			// degrading sound
+			// pthread_mutex_lock(&lpDevice->mutex);
+
+			if (lpDevice->nb_clients > 0) {
+				// Retrieve data for client where it is available
+				for (i = 0; i < MAXCLIENTSPERDEVICE; i++) {
+					if (lpDevice->clients[i].lives) {
+						pthread_mutex_lock(&lpDevice->clients[i].mutex);
+
+						if (lpDevice->clients[i].ring_in != lpDevice->clients[i].ring_out) {
+							// Get ring buffer
+							pcm_buffers[i] = lpDevice->clients[i].ring[lpDevice->clients[i].ring_out];
+							pcm_buffers_size[i] = lpDevice->clients[i].ring_len[lpDevice->clients[i].ring_out];
+							// Tell client we got them
+							lpDevice->clients[i].ring[lpDevice->clients[i].ring_out] = NULL;
+							lpDevice->clients[i].ring_len[lpDevice->clients[i].ring_out] = 0;
+
+							// Move to next ring
+							int next_ring = ((lpDevice->clients[i].ring_out + 1) % MAXCLIENTSRINGSIZE);
+
+							//printf("Reading pool %d[ %d] = %p\n", i, lpDevice->clients[i].ring_out, pcm_buffers[i]);
+
+							lpDevice->clients[i].ring_out = next_ring;
+
+							// Remember we got some sound
+							state_current = SOUND;
+						}
+
+						pthread_mutex_unlock(&lpDevice->clients[i].mutex);
+					}
+				}
+			}
+			//FIXME 
+			// pthread_mutex_unlock(&lpDevice->mutex);
+
+			// Send mixed audio stream to clients
+			switch (state_current) {
+			case SOUND:
+				pcm_buffer_filed_size = audio_mixer(pcm_buffer, pcm_buffers, pcm_buffers_size, lpDevice->mixer.volume_speaker_left, lpDevice->mixer.volume_speaker_right);
+
+				// Free no longer used audio blocks
+				for (i = 0; i < MAXCLIENTSPERDEVICE; i++) {
+					if (pcm_buffers[i]) {
+						// Reintegrate data where they come from
+						pool_push(pcm_buffers[i]);
+					}
+				}
+
+				/////////////////////////////////
+				// Transfer data to bluetooth
+				/////////////////////////////////
+
+				if (pcm_buffer && pcm_buffer_filed_size > 0) {
+					// Transfer takes place by A2DPD_BLOCK_SIZE bytes blocks
+					int blockstart = 0;
+					int blocksize = A2DPD_BLOCK_SIZE;
+
+					// Allocate A2DP if we are not connected
+					if (!lpA2dp) {
+						// Select the good device
+						lpDevice->bredirectalsa = read_config_int(g_srcfilename, "a2dpd", "enableredirectalsa", 0);
+						read_config_string(g_srcfilename, "a2dpd", "address", lpDevice->addr, sizeof(lpDevice->addr), "");
+						read_config_string(g_srcfilename, "a2dpd", "alsaoutput", lpDevice->plug, sizeof(lpDevice->plug), "");
+						// Allocate it
+						if (lpDevice->bredirectalsa)
+							lpA2dp = alsa_new(lpDevice->plug, rate);
+						else
+							lpA2dp = a2dp_new(lpDevice->addr, rate);
+						g_nbdeviceconnected++;
+						destroy_count = 0;
+					}
+
+					if (lpA2dp) {
+						// Send data to BT headset
+						while (!bError && blockstart < pcm_buffer_filed_size) {
+							int transfer;
+
+							blocksize = (pcm_buffer_filed_size < A2DPD_BLOCK_SIZE) ? pcm_buffer_filed_size : A2DPD_BLOCK_SIZE;
+
+							if (lpDevice->bredirectalsa)
+								transfer = alsa_transfer_raw(lpA2dp, pcm_buffer + blockstart, blocksize);
+							else
+								transfer = a2dp_transfer_raw(lpA2dp, pcm_buffer + blockstart, blocksize);
+
+							if (transfer >= 0) {
+								destroy_count = 0;
+								blockstart += blocksize;
+								ibytespersecond += transfer;
+								a2dp_timer_notifyframe(&TimerInfos);
+							} else {
+								printf("Error in a2dp_transfer_raw\n");
+								bError = 1;
+							}
+						}
+					}
+				}
+				break;
+			case NOSOUND:
+				if (state_previous == SOUND) {
+					//printf("Sound stream ran dry!!!\n");
+				}
+				break;
+			}
+
+			// Wait must take place after sending a packet
+			// This way, you will allow the plugin to send it's data
+			// And you will collect the new data
+			// Time reference floating because of 44100/1000 error in integer calculation
+			a2dp_timer_sleep(&TimerInfos, A2DPTIMERPREDELAY);
+
+			// Read config file changes each second
+			if (TimerInfos.display > 0) {
+				if(g_brereadconfig) {
+					char addr[20];
+					char plug[20];
+					int bredirectalsa = read_config_int(g_srcfilename, "a2dpd", "enableredirectalsa", 0);
+					read_config_string(g_srcfilename, "a2dpd", "address", addr, sizeof(addr), "");
+					read_config_string(g_srcfilename, "a2dpd", "alsaoutput", plug, sizeof(plug), "");
+					if((strcmp(addr, lpDevice->addr) != 0) || (strcmp(plug, lpDevice->plug) != 0) || (bredirectalsa != lpDevice->bredirectalsa)) {
+						// Force destroy, device will be recreated upon audio incoming
+						destroy_count=10000;
+					}
+				}
+				/*
+				   char* lpszFormat = "A2DPD: [%d,%d|%d,%d] %s %s clients=%d freq=%d[%d b/s] sleep=%d satur=%d\n";
+				   if(satured==0) lpszFormat = "A2DPD: [%d,%d|%d,%d] %s %s clients=%d freq=%d[%d b/s]\n";
+				   printf(lpszFormat, 
+				   lpDevice->mixer.volume_speaker_left,
+				   lpDevice->mixer.volume_speaker_right,
+				   lpDevice->mixer.volume_micro_left,
+				   lpDevice->mixer.volume_micro_right,
+				   (state_current==SOUND)?"playing":"silent",
+				   lpA2dp?"connected":"disconnected", lpDevice->nb_clients, TimerInfos.display,
+				   ibytespersecond,
+				   satured);
+				   // Reset all variables used
+				   ibytespersecond=0;
+				   satured=0;
+				 */
+			}
+
+			// Free the A2DP device if needed
+			// When destroy_count reaches 2000 we will destroy the A2DP link
+			// However, destroy_count is reset whenever data are sent
+			destroy_count++;
+			if (lpA2dp && destroy_count > 2000) {
+				printf("Destroying lpA2dp, destroy_count is %d\n", destroy_count);
+				g_nbdeviceconnected--;
+				if (lpDevice->bredirectalsa)
+					alsa_destroy(lpA2dp);
+				else
+					a2dp_destroy(lpA2dp);
+				lpA2dp = NULL;
+			}
+
+			state_previous = state_current;
+		}
+		pool_push(pcm_buffer);
+
+		// Sleep a little bit before retrying
+		if (!bSigINTReceived)
+			sleep(1);
+
+		// Free A2DP
+		if (lpA2dp) {
+			printf("Destroying lpA2dp, end of loop\n");
+			g_nbdeviceconnected--;
+			if (lpDevice->bredirectalsa)
+				alsa_destroy(lpA2dp);
+			else
+				a2dp_destroy(lpA2dp);
+			lpA2dp = NULL;
+		}
+	}
 
-        iThreadsRunning --;
+	iThreadsRunning--;
 
-        return 0;
+	return 0;
 }
 
 // This function handle the bluetooth connection
-void* avdtp_listener(void* param)
+void *avdtp_listener(void *param)
 {
-        // We should not terminate the process if clients are still running
-        iThreadsRunning ++;
+	// We should not terminate the process if clients are still running
+	iThreadsRunning++;
 
-        LPBTA2DPPERDEVICEDATA lpDevice = (LPBTA2DPPERDEVICEDATA)param;
-        pthread_detach(lpDevice->thread);
+	LPBTA2DPPERDEVICEDATA lpDevice = (LPBTA2DPPERDEVICEDATA) param;
+	pthread_detach(lpDevice->thread);
 
-        // As long as daemon is running
-        printf("avdtp: Accepting incoming connection\n");
-        while(!bSigINTReceived)
-        {
-                int sockfd = a2dp_make_listen_socket( 25);
-                if(sockfd>=0)
-                {
-                        while(!bSigINTReceived)
-                        {
-                                // Wait for incoming connections
-                                char szRemote[64];
-                                uint16_t iMTU = 0;
-
-                                int new_fd = a2dp_wait_connection(sockfd, szRemote, sizeof(szRemote), &iMTU);
-
-                                if(new_fd>0)
-                                {
-                                        printf("avdtp: socket %d: Connection from %s, mtu=%d\n", new_fd, szRemote, iMTU);
-
-                                        // Loop and manage what the client sends
-                                        setup_socket(new_fd);
-                                        int iReceived = 0;
-                                        int play = 0;
-                                        int count = 0;
-                                        do
-                                        {
-                                                iReceived = a2dp_handle_avdtp_message(NULL, new_fd, NULL, NULL, 0);
-                                                if(iReceived==0)
-                                                {
-                                                        printf("avdtp: socket %d: Received frame, start %s\n", new_fd, g_sCmdNew);
-                                                        play=1;
-                                                        count=0;
-                                                        break;
-                                                }
-                                                else if(iReceived<0)
-                                                {
-                                                        if(errno!=EAGAIN)
-                                                                printf("avdtp: socket %d: Received failed result=%d (errno=%d:%s)\n", new_fd, iReceived, errno, strerror(errno));
-                                                }
-                                                count++;
-                                        }
-                                        // AVDTP do not need to have a device connected, since it can establish device connection
-                                        while(!bSigINTReceived && (iReceived>=0 || errno==EAGAIN) && count<10);
-                                        printf("avdtp: socket %d: timed out\n", new_fd);
-                                        close_socket(new_fd);
-
-                                        if(play&&g_sCmdNew[0])
-                                        {
-                                                async_run_process(g_sCmdNew);
-                                        }
-                                }
-                                else
-                                {
-                                        if(errno!=EAGAIN)
-                                        {
-                                                printf("a2dp_wait_connection failed (AVDTP socket) : %d (errno=%d:%s)\n", new_fd, errno, strerror(errno));
-                                                break;
-                                        }
-                                }
-                        }
-
-                        close_socket(sockfd);
-                }
-
-                // Sleep a little bit if we must retry
-                sleep(bSigINTReceived?1:0);
-        }
+	// As long as daemon is running
+	printf("avdtp: Accepting incoming connection\n");
+	while (!bSigINTReceived) {
+		int sockfd = a2dp_make_listen_socket(25);
+		if (sockfd >= 0) {
+			while (!bSigINTReceived) {
+				// Wait for incoming connections
+				char szRemote[64];
+				uint16_t iMTU = 0;
+
+				int new_fd = a2dp_wait_connection(sockfd, szRemote, sizeof(szRemote), &iMTU);
+
+				if (new_fd > 0) {
+					printf("avdtp: socket %d: Connection from %s, mtu=%d\n", new_fd, szRemote, iMTU);
+
+					// Loop and manage what the client sends
+					setup_socket(new_fd);
+					int iReceived = 0;
+					int play = 0;
+					int count = 0;
+					do {
+						iReceived = a2dp_handle_avdtp_message(NULL, new_fd, NULL, NULL, 0);
+						if (iReceived == 0) {
+							printf("avdtp: socket %d: Received frame, start %s\n", new_fd, g_sCmdNew);
+							play = 1;
+							count = 0;
+							break;
+						} else if (iReceived < 0) {
+							if (errno != EAGAIN)
+								printf("avdtp: socket %d: Received failed result=%d (errno=%d:%s)\n", new_fd, iReceived, errno, strerror(errno));
+						}
+						count++;
+					}
+					// AVDTP do not need to have a device connected, since it can establish device connection
+					while (!bSigINTReceived && (iReceived >= 0 || errno == EAGAIN)
+					       && count < 10);
+					printf("avdtp: socket %d: timed out\n", new_fd);
+					close_socket(new_fd);
+
+					if (play && g_sCmdNew[0]) {
+						async_run_process(g_sCmdNew);
+					}
+				} else {
+					if (errno != EAGAIN) {
+						printf("a2dp_wait_connection failed (AVDTP socket) : %d (errno=%d:%s)\n", new_fd, errno, strerror(errno));
+						break;
+					}
+				}
+			}
 
-        iThreadsRunning --;
+			close_socket(sockfd);
+		}
+		// Sleep a little bit if we must retry
+		sleep(bSigINTReceived ? 1 : 0);
+	}
 
-        return 0;
+	iThreadsRunning--;
+
+	return 0;
 }
 
 // This function handle the bluetooth connection
-void* avrcp_listener(void* param)
+void *avrcp_listener(void *param)
 {
-        // We should not terminate the process if clients are still running
-        iThreadsRunning ++;
+	// We should not terminate the process if clients are still running
+	iThreadsRunning++;
+
+	LPBTA2DPPERDEVICEDATA lpDevice = (LPBTA2DPPERDEVICEDATA) param;
+	pthread_detach(lpDevice->thread);
 
-        LPBTA2DPPERDEVICEDATA lpDevice = (LPBTA2DPPERDEVICEDATA)param;
-        pthread_detach(lpDevice->thread);
+	// As long as daemon is running
+	printf("avrcp: Accepting incoming connection\n");
+	while (!bSigINTReceived) {
+		int sockfd = a2dp_make_listen_socket(23);
+		if (sockfd >= 0) {
+			while (!bSigINTReceived) {
+				// Wait for incoming connections
+				char szRemote[64];
+				uint16_t iMTU = 0;
+
+				int new_fd = a2dp_wait_connection(sockfd, szRemote,
+								  sizeof(szRemote),
+								  &iMTU);
+
+				if (new_fd > 0) {
+					printf("avrcp: socket %d: Connection from %s, mtu=%d\n", new_fd, szRemote, iMTU);
+					// Loop and manage what the client sends
+					setup_socket(new_fd);
+					int iReceived = 0;
+					do {
+						printf("avrcp: socket %d: Reading from %s, mtu=%d\n", new_fd, szRemote, iMTU);
+						errno = 0;
+						iReceived = a2dp_handle_avrcp_message(new_fd);
+					}
+					// AVRCP need device connected
+					while (g_nbdeviceconnected && !bSigINTReceived && (iReceived > 0 || errno == EAGAIN));
+					printf("avrcp: socket %d: timed out\n", new_fd);
+					close_socket(new_fd);
+				} else if (errno != EAGAIN) {
+					printf("a2dp_wait_connection failed (AVRCP socket) : %d (errno=%d:%s)\n", new_fd, errno, strerror(errno));
+					break;
+				}
+			}
 
-        // As long as daemon is running
-        printf("avrcp: Accepting incoming connection\n");
-        while(!bSigINTReceived)
-        {
-                int sockfd = a2dp_make_listen_socket( 23);
-                if(sockfd>=0)
-                {
-                        while(!bSigINTReceived)
-                        {
-                                // Wait for incoming connections
-                                char szRemote[64];
-                                uint16_t iMTU = 0;
-
-                                int new_fd = a2dp_wait_connection(sockfd, szRemote, sizeof(szRemote), &iMTU);
-
-                                if(new_fd>0)
-                                {
-                                        printf("avrcp: socket %d: Connection from %s, mtu=%d\n", new_fd, szRemote, iMTU);
-                                        // Loop and manage what the client sends
-                                        setup_socket(new_fd);
-                                        int iReceived = 0;
-                                        do
-                                        {
-                                                iReceived = a2dp_handle_avrcp_message(new_fd);
-                                        }
-                                        // AVRCP need device connected
-                                        while(g_nbdeviceconnected && !bSigINTReceived && (iReceived>0 || errno==EAGAIN));
-                                        printf("avrcp: socket %d: timed out\n", new_fd);
-                                        close_socket(new_fd);
-                                }
-                                else
-                                {
-                                        if(errno!=EAGAIN)
-                                        {
-                                                printf("a2dp_wait_connection failed (AVRCP socket) : %d (errno=%d:%s)\n", new_fd, errno, strerror(errno));
-                                                break;
-                                        }
-                                }
-                        }
-
-                        close_socket(sockfd);
-                }
-
-                // Sleep a little bit if we must retry
-                sleep(bSigINTReceived?1:0);
-        }
+			close_socket(sockfd);
+		}
+		// Sleep a little bit if we must retry
+		sleep(bSigINTReceived ? 1 : 0);
+	}
 
-        iThreadsRunning --;
+	iThreadsRunning--;
 
-        return 0;
+	return 0;
 }
 
 // server processing loop
-void main_loop(char* addr)
+void main_loop(char *addr)
 {
-        while(!bSigINTReceived)
-        {
-                // Master socket
-                int sockfd = make_server_socket();
-
-                if(sockfd>0)
-                {
-                        LPBTA2DPPERDEVICEDATA lpDevice = bta2dpdevicenew(addr);
-                        // Set pthread stack size to decrease unused memory usage
-                        pthread_attr_t tattr;
-                        size_t size = PTHREAD_STACK_MIN;
-                        int ret = pthread_attr_init(&tattr);
-                        ret = pthread_attr_setstacksize(&tattr, size);
-                        pthread_create(&lpDevice->thread, &tattr, bt_handler,  lpDevice);
-                        pthread_create(&lpDevice->thread, &tattr, avrcp_listener, lpDevice);
-                        pthread_create(&lpDevice->thread, &tattr, avdtp_listener, lpDevice);
-
-                        while(!bSigINTReceived)
-                        {
-                                int new_fd = -1;
-                                printf("Accepting incoming tcp stream connection\n");
-                                new_fd=accept_socket(sockfd);
-                                printf("Accepted %d\n", new_fd);
-
-                                // Handle connection if it is not the final dummy client
-                                if(!bSigINTReceived)
-                                {
-                                        LPA2DPDCLIENT lpClient = malloc(sizeof(A2DPDCLIENT));
-                                        lpClient->lpDevice = lpDevice;
-                                        lpClient->sockfd = new_fd;
-                                        
-                                        pthread_mutex_lock(&lpClient->lpDevice->mutex);
-                                        lpClient->lpDevice->nb_clients++;
-                                        pthread_mutex_unlock(&lpClient->lpDevice->mutex);
-                                        
-                                        pthread_create(&lpClient->thread, &tattr, client_handler, lpClient);
-                                }
-                                else
-                                {
-                                        close_socket(new_fd);
-                                }
-                                usleep(10000);
-                        }
-        
-                        close_socket(sockfd);
-        
-                        // Very minor race condition here
-                        // No dramatic consequences
-                        // But we Must wait all client termination
-                        // We will pthread_join one day
-                        int icount = 0;
-                        while(iThreadsRunning>0 && icount<30)
-                        {
-                                printf("A2DPD still %d clients running\n", iThreadsRunning);
-                                icount++;
-                                sleep(1);
-                        }
-        
-                        // Free informations on the device
-                        bta2dpdevicefree(lpDevice);
-                        pthread_attr_destroy(&tattr);
-                }
-                else
-                {
-                        printf("Error %d: cannot get the socket errno=%d (%s)\n", sockfd, errno, strerror(errno));
-                }
+	while (!bSigINTReceived) {
+		// Master socket
+		int sockfd = make_server_socket();
+
+		if (sockfd > 0) {
+			LPBTA2DPPERDEVICEDATA lpDevice = bta2dpdevicenew(addr);
+			// Set pthread stack size to decrease unused memory usage
+			pthread_attr_t tattr;
+			pthread_t havrcp, havdtp;
+			size_t size = PTHREAD_STACK_MIN;
+			int ret = pthread_attr_init(&tattr);
+			ret = pthread_attr_setstacksize(&tattr, size);
+			pthread_create(&lpDevice->thread, &tattr, bt_handler, lpDevice);
+			if (g_bavrcp)
+				pthread_create(&havrcp, &tattr, avrcp_listener, lpDevice);
+			if (g_bavrcp)
+				pthread_create(&havdtp, &tattr, avdtp_listener, lpDevice);
+
+			while (!bSigINTReceived) {
+				int new_fd = -1;
+				printf("main_thread:Accepting incoming tcp stream connection\n");
+				new_fd = accept_socket(sockfd);
+				printf("main_thread: Accepted %d\n", new_fd);
+
+				// Handle connection if it is not the final dummy client
+				if (!bSigINTReceived && new_fd > 0) {
+					LPA2DPDCLIENT lpClient = malloc(sizeof(A2DPDCLIENT));
+					lpClient->lpDevice = lpDevice;
+					lpClient->sockfd = new_fd;
+
+					pthread_mutex_lock(&lpClient->lpDevice->mutex);
+					lpClient->lpDevice->nb_clients++;
+					pthread_mutex_unlock(&lpClient->lpDevice->mutex);
+
+					pthread_create(&lpClient->thread, &tattr, client_handler, lpClient);
+				} else if (new_fd > 0) {
+					close_socket(new_fd);
+				}
+				usleep(10000);
+			}
+
+			close_socket(sockfd);
+
+			// Very minor race condition here
+			// No dramatic consequences
+			// But we Must wait all client termination
+			// We will pthread_join one day
+			int icount = 0;
+			while (iThreadsRunning > 0 && icount < 30) {
+				printf("A2DPD still %d clients running\n", iThreadsRunning);
+				icount++;
+				sleep(1);
+			}
+
+			// Free informations on the device
+			bta2dpdevicefree(lpDevice);
+			pthread_attr_destroy(&tattr);
+		} else {
+			printf("Error %d: cannot get the socket errno=%d (%s)\n", sockfd, errno, strerror(errno));
+		}
 
-                sleep(1);
-        }
+		sleep(1);
+	}
 }
 
 
@@ -1045,90 +1004,73 @@
 // main function
 int main(int argc, char *argv[])
 {
-        int i = 0;
-	int fd;
-        struct timespec timer_resolution = { 0, 0 };
-        char address[256] = "";
-        char* addr = &address[0];
-        char* sonorix="00:0A:56:00:C0:C2";
-        //char* iphono420= "C2:00:08:F4:30:07:64";
-        //char* hpheadphone= "00:0D:44:2A:17:C7";
-        struct sched_param schedparam = { sched_get_priority_max(SCHED_FIFO) };
-        int res=0,  bFork=0, bVerbose=1, bKill=0;
+	int i = 0;
+	struct timespec timer_resolution = { 0, 0 };
+	char address[256] = "";
+	char *addr = &address[0];
+	char *sonorix = "00:0A:56:00:C0:C2";
+	//char* iphono420= "C2:00:08:F4:30:07:64";
+	//char* hpheadphone= "00:0D:44:2A:17:C7";
+	struct sched_param schedparam = { sched_get_priority_max(SCHED_FIFO) };
+	int res = 0, bFork = 0, bVerbose = 1, bKill = 0, fd = 0;
 	FILE *fp;
 	pid_t pid;
 
-        // Read config values from config file
-        get_config_filename(g_srcfilename, sizeof(g_srcfilename));
-        read_config_string(g_srcfilename, "a2dpd", "address",  address,     sizeof(address),     sonorix);
-        read_config_string(g_srcfilename, "a2dpd", "cmdplay",  g_sCmdPlay,  sizeof(g_sCmdPlay),  "");
-        read_config_string(g_srcfilename, "a2dpd", "cmdpause", g_sCmdPause, sizeof(g_sCmdPause), "");
-        read_config_string(g_srcfilename, "a2dpd", "cmdprev",  g_sCmdPrev,  sizeof(g_sCmdPrev),  "");
-        read_config_string(g_srcfilename, "a2dpd", "cmdnext",  g_sCmdNext,  sizeof(g_sCmdNext),  "");
-        read_config_string(g_srcfilename, "a2dpd", "cmdnew",   g_sCmdNew,   sizeof(g_sCmdNew),  "");
-        read_config_string(g_srcfilename, "a2dpd", "logfile",  g_sOutputFilename,  sizeof(g_sOutputFilename),  "/dev/null");
-
-        // Parse command line parameters
-        for(i=1; i<argc && argv[i]!=NULL; i++)
-        {
-                char c;
-                // Search a bluetooth addr
-                if(sscanf(argv[i], "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", &c, &c, &c, &c, &c, &c, &c, &c, &c, &c, &c, &c)==12)
-                {
-                        addr=argv[i];
-                }
-                else if(!strcmp(argv[i], "-n"))
-                {
-                        bFork=0;
-                }
-                else if(!strcmp(argv[i], "-d"))
-                {
-                        bFork=1;
-                }
-                else if(!strcmp(argv[i], "-v"))
-                {
-                        bVerbose=1;
-                }
-		else if(!strcmp(argv[i], "-k"))
-		{
-			bKill=1;
-		}
-                else if(!strcmp(argv[i], "+n"))
-                {
-                        bFork=1;
-                }
-                else if(!strcmp(argv[i], "+d"))
-                {
-                        bFork=0;
-                }
-                else if(!strcmp(argv[i], "+v"))
-                {
-                        bVerbose=0;
-                }
-                else
-                {
-                        printf("Parameter not handled: %s\r\n", argv[i]);
-                }
-        }
-        clock_getres(CLOCK_REALTIME, &timer_resolution);
-
-	init_uinput ();
-
-        ignore_child_processes_return_values();
-        
-        // Redirect outputs
-        make_daemon_process(bFork, bVerbose, g_sOutputFilename);
+	// Read config values from config file
+	get_config_filename(g_srcfilename, sizeof(g_srcfilename));
+	read_config_string(g_srcfilename, "a2dpd", "address", address, sizeof(address), sonorix);
+	read_config_string(g_srcfilename, "a2dpd", "cmdplay", g_sCmdPlay, sizeof(g_sCmdPlay), "");
+	read_config_string(g_srcfilename, "a2dpd", "cmdpause", g_sCmdPause, sizeof(g_sCmdPause), "");
+	read_config_string(g_srcfilename, "a2dpd", "cmdprev", g_sCmdPrev, sizeof(g_sCmdPrev), "");
+	read_config_string(g_srcfilename, "a2dpd", "cmdnext", g_sCmdNext, sizeof(g_sCmdNext), "");
+	read_config_string(g_srcfilename, "a2dpd", "cmdnew", g_sCmdNew, sizeof(g_sCmdNew), "");
+	read_config_string(g_srcfilename, "a2dpd", "logfile", g_sOutputFilename, sizeof(g_sOutputFilename), "/dev/null");
+	g_brereadconfig = read_config_int(g_srcfilename, "a2dpd", "enablerereadconfig", 1);
+	g_breversestereo = read_config_int(g_srcfilename, "a2dpd", "enablereversestereo", 0);
+	g_bavrcp = read_config_int(g_srcfilename, "a2dpd", "enableavrcp", 1);
+
+	// Parse command line parameters
+	for (i = 1; i < argc && argv[i] != NULL; i++) {
+		char c;
+		// Search a bluetooth addr
+		if (sscanf(argv[i], "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", &c, &c, &c, &c, &c, &c, &c, &c, &c, &c, &c, &c) == 12) {
+			addr = argv[i];
+		} else if (!strcmp(argv[i], "-n")) {
+			bFork = 0;
+		} else if (!strcmp(argv[i], "-d")) {
+			bFork = 1;
+		} else if (!strcmp(argv[i], "-v")) {
+			bVerbose = 1;
+		} else if (!strcmp(argv[i], "-k")) {
+			bKill = 1;
+		} else if (!strcmp(argv[i], "+n")) {
+			bFork = 1;
+		} else if (!strcmp(argv[i], "+d")) {
+			bFork = 0;
+		} else if (!strcmp(argv[i], "+v")) {
+			bVerbose = 0;
+		} else {
+			printf("Parameter not handled: %s\r\n", argv[i]);
+		}
+	}
+	clock_getres(CLOCK_REALTIME, &timer_resolution);
+
+	init_uinput();
 
+	ignore_child_processes_return_values();
+
+	// Redirect outputs
+	make_daemon_process(bFork, bVerbose, g_sOutputFilename);
 	// Generate the lockfile
 	fd = open(PIDFILE, O_RDWR | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
 
 	if (fd == -1) {
-		if (errno != EEXIST) // If we can't write the lock, then ignore
+		if (errno != EEXIST)	// If we can't write the lock, then ignore
 			goto post_lock;
-		
+
 		if ((fd = open(PIDFILE, O_RDWR)) < 0)
 			goto post_lock;
-		
+
 		fp = fdopen(fd, "rw");
 		if (fp == NULL)
 			goto post_lock;
@@ -1136,25 +1078,24 @@
 		pid = -1;
 		if ((fscanf(fp, "%d", &pid) != 1) || (pid == getpid())
 		    || (lock_fd(fileno(fp)) == 0)) {
-			unlink (PIDFILE);
+			unlink(PIDFILE);
 		} else {
 			if (bKill) {
-				kill (pid, 15);
-				sleep (5); // let the other daemon die
+				kill(pid, 15);
+				sleep(5);	// let the other daemon die
 			} else
 				goto shutdown;
 		}
 		fclose(fp);
 
 		unlink(PIDFILE);
-		fd = open(PIDFILE, O_RDWR | O_CREAT | O_EXCL,
-			  S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
+		fd = open(PIDFILE, O_RDWR | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
 
 		if (fd == -1)
 			goto post_lock;
-		
+
 	}
-	
+
 	lock_fd(fd);
 
 	fp = fdopen(fd, "w");
@@ -1162,31 +1103,30 @@
 	fflush(fp);
 	fcntl(fd, F_SETFD, (long) 1);
 
- post_lock:
-        printf("%s addr=%s timer=%d us [%s %s]\n", argv[0], addr, (int)(timer_resolution.tv_nsec/1000), __DATE__, __TIME__);
+      post_lock:
+	printf("%s addr=%s timer=%d us [%s %s]\n", argv[0], addr, (int) (timer_resolution.tv_nsec / 1000), __DATE__, __TIME__);
 
-        // If we can be realtime it will be better
-        res = sched_setscheduler(0, SCHED_FIFO, &schedparam); 
-        printf("setscheduler returns %d (errno=%d:%s)\n", res, errno, strerror(errno));
+	// If we can be realtime it will be better
+	res = sched_setscheduler(0, SCHED_FIFO, &schedparam);
+	printf("setscheduler returns %d (errno=%d:%s)\n", res, errno, strerror(errno));
 
-        // set up the handler
-        signal(SIGINT, sigint_handler);
-        signal(SIGTERM, sigint_handler);
+	// set up the handler
+	signal(SIGINT, sigint_handler);
+	signal(SIGTERM, sigint_handler);
 
-        // global initialisations
-        a2dp_init();
+	// global initialisations
+	a2dp_init();
 
-        // Run main loop
-        main_loop(addr);
+	// Run main loop
+	main_loop(addr);
 
-        // global free
-        a2dp_exit();
+	// global free
+	a2dp_exit();
 
 	kill_uinput();
 
-shutdown:
-        printf("A2DPD terminated succesfully\n");
+      shutdown:
+	printf("A2DPD terminated succesfully\n");
 
-        return 0;
+	return 0;
 }
-
Index: alsa-plugins/a2dpd_protocol.h
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/alsa-plugins/a2dpd_protocol.h,v
retrieving revision 1.3
diff -u -r1.3 a2dpd_protocol.h
--- alsa-plugins/a2dpd_protocol.h	17 Aug 2006 14:06:27 -0000	1.3
+++ alsa-plugins/a2dpd_protocol.h	31 Aug 2006 15:58:57 -0000
@@ -26,12 +26,11 @@
 
 
 // parameters used to describe device state
-typedef struct
-{
-        int16_t                     volume_speaker_right;
-        int16_t                     volume_speaker_left;
-        int16_t                     volume_micro_right;
-        int16_t                     volume_micro_left;
+typedef struct {
+	int16_t volume_speaker_right;
+	int16_t volume_speaker_left;
+	int16_t volume_micro_right;
+	int16_t volume_micro_left;
 } AUDIOMIXERDATA;
 
 #define INVALIDAUDIOMIXERDATA   { -1, -1, -1, -1 }
@@ -44,8 +43,8 @@
 #define A2DPD_VOLUME_MIN        0
 #define A2DPD_VOLUME_MAX        15
 
-#define A2DPD_FRAME_BYTES       4 // 16bits * 2 channels
-#define A2DPD_FRAME_RATE        44100 // Can be 32000, tested with HP, iPhono and needed Sonorix, but quality decreases, 48000 nearly never works
+#define A2DPD_FRAME_BYTES       4	// 16bits * 2 channels
+#define A2DPD_FRAME_RATE        44100	// Can be 32000, tested with HP, iPhono and needed Sonorix, but quality decreases, 48000 nearly never works
 // a2dp->sbc.channels*44100*2/(size*a2dp->frame_bytes);
 // 344.53125=channels*freq*16 bits/sizeof(buf)
 #define A2DPD_BLOCK_SIZE        (512*1)
Index: alsa-plugins/a2dplib.c
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/alsa-plugins/a2dplib.c,v
retrieving revision 1.5
diff -u -r1.5 a2dplib.c
--- alsa-plugins/a2dplib.c	30 Aug 2006 14:43:21 -0000	1.5
+++ alsa-plugins/a2dplib.c	31 Aug 2006 15:58:57 -0000
@@ -79,7 +79,7 @@
 #define A2DP_SERVICE_NAME	"A2DP Audio Source"
 #define A2DP_VERSION        0x0100
 
-static struct sigaction        actions;
+static struct sigaction actions;
 /*
 sdp_record_t* a2dp_advertise_sdp(sdp_session_t* sdpSessionP)
 {
@@ -158,1128 +158,1026 @@
 void a2dp_init(void) __attribute__ ((constructor));
 void a2dp_exit(void) __attribute__ ((destructor));
 */
-void memcpy_changeendian( void* dst, const void *src, int size)
+void memcpy_changeendian(void *dst, const void *src, int size)
 {
-        int i;
-        const uint16_t* ptrsrc=src;
-        uint16_t* ptrdst=dst;
-        for(i = 0; i < size/2; i ++)
-        {
-                *ptrdst++ = htons(*ptrsrc++);
-        }
+	int i;
+	const uint16_t *ptrsrc = src;
+	uint16_t *ptrdst = dst;
+	for (i = 0; i < size / 2; i++) {
+		*ptrdst++ = htons(*ptrsrc++);
+	}
 }
 
 // Prepare packet headers
-void init_request(struct avdtp_header * header, int request_id)
+void init_request(struct avdtp_header *header, int request_id)
 {
-        static int transaction = 0;
+	static int transaction = 0;
 
-        header->packet_type = PACKET_TYPE_SINGLE;
-        header->message_type = MESSAGE_TYPE_COMMAND;
-        header->transaction_label = transaction;
-        header->signal_id = request_id;
+	header->packet_type = PACKET_TYPE_SINGLE;
+	header->message_type = MESSAGE_TYPE_COMMAND;
+	header->transaction_label = transaction;
+	header->signal_id = request_id;
 
-        // clear rfa bits
-        header->rfa0 = 0;
+	// clear rfa bits
+	header->rfa0 = 0;
 
-        transaction = (transaction + 1) & 0xf;
+	transaction = (transaction + 1) & 0xf;
 }
 
 // Analyse the SEIDs the sink has sent to us
-int process_seid(int s, struct acp_seid_info * get_seid_resp, unsigned short *psm, sbc_t *sbc)
+int process_seid(int s, struct acp_seid_info *get_seid_resp, unsigned short *psm, sbc_t * sbc)
 {
-        int v, size;
-        int seid = get_seid_resp->acp_seid;
-        struct getcap_req put_req;
-        struct getcap_resp cap_resp;
-        struct set_config s_config;
-        struct set_config_resp s_resp;
-        struct stream_cmd open_stream;
-        struct open_stream_rsp open_resp;
-
-        memset(&put_req, 0, sizeof(put_req));
-        init_request(&put_req.header, AVDTP_GET_CAPABILITIES);
-        put_req.acp_seid = seid;
+	int v, size;
+	int seid = get_seid_resp->acp_seid;
+	struct getcap_req put_req;
+	struct getcap_resp cap_resp;
+	struct set_config s_config;
+	struct set_config_resp s_resp;
+	struct stream_cmd open_stream;
+	struct open_stream_rsp open_resp;
+
+	memset(&put_req, 0, sizeof(put_req));
+	init_request(&put_req.header, AVDTP_GET_CAPABILITIES);
+	put_req.acp_seid = seid;
+
+	if (write(s, &put_req, sizeof(put_req)) != sizeof(put_req)) {
+		DBG("Couldn't request capabilities for SEID = %d", seid);
+		return (-1);
+	}
 
-        if (write(s, &put_req, sizeof(put_req)) != sizeof(put_req))
-        {
-                DBG("Couldn't request capabilities for SEID = %d", seid);
-                return (-1);
-        }
+	if (read(s, &cap_resp, sizeof(cap_resp)) < sizeof(cap_resp) ||
+	    cap_resp.header.message_type == MESSAGE_TYPE_REJECT || cap_resp.media_type != AUDIO_MEDIA_TYPE || cap_resp.media_codec_type != SBC_MEDIA_CODEC_TYPE) {
+		DBG("Didn't receive SBC codec parameters (first) for SEID = %d", seid);
+		return (-1);
+	}
 
-        if (read(s, &cap_resp, sizeof(cap_resp)) < sizeof(cap_resp) ||
-                        cap_resp.header.message_type == MESSAGE_TYPE_REJECT ||
-                        cap_resp.media_type != AUDIO_MEDIA_TYPE ||
-                        cap_resp.media_codec_type != SBC_MEDIA_CODEC_TYPE) {
-                DBG("Didn't receive SBC codec parameters (first) for SEID = %d", seid);
-                return (-1);
-        }
+	DBG("Got capabilities response:\nservcap_cap=%d, servcap_len=%d,\ncap_type=%d, length=%d, media_type=%d, codec=%d",
+	    cap_resp.serv_cap, cap_resp.serv_cap_len, cap_resp.cap_type, cap_resp.length, cap_resp.media_type, cap_resp.media_codec_type);
 
-        DBG("Got capabilities response:\nservcap_cap=%d, servcap_len=%d,\ncap_type=%d, length=%d, media_type=%d, codec=%d",
-                cap_resp.serv_cap,
-                cap_resp.serv_cap_len,
-                cap_resp.cap_type,
-                cap_resp.length,
-                cap_resp.media_type,
-                cap_resp.media_codec_type
-        );
-
-        memset(&s_config, 0, sizeof(s_config));
-        init_request(&s_config.header, AVDTP_SET_CONFIGURATION);
-        s_config.serv_cap = MEDIA_TRANSPORT_CATEGORY;
-        s_config.acp_seid = seid;
-        s_config.int_seid = 1;	//FIXME how should I choose the int_seid??
-        s_config.cap_type = MEDIA_CODEC;
-        s_config.length = 6;
-        s_config.media_type = AUDIO_MEDIA_TYPE;
-        s_config.media_codec_type = SBC_MEDIA_CODEC_TYPE;
-
-        switch(sbc->channels) {
-        case 1:
-                v = 8;
-                break;
-        case 2:
-        default:
-                v = 2;
-                break;
-        }
-        s_config.codec_elements.sbc_elements.channel_mode = v;
+	memset(&s_config, 0, sizeof(s_config));
+	init_request(&s_config.header, AVDTP_SET_CONFIGURATION);
+	s_config.serv_cap = MEDIA_TRANSPORT_CATEGORY;
+	s_config.acp_seid = seid;
+	s_config.int_seid = 1;	//FIXME how should I choose the int_seid??
+	s_config.cap_type = MEDIA_CODEC;
+	s_config.length = 6;
+	s_config.media_type = AUDIO_MEDIA_TYPE;
+	s_config.media_codec_type = SBC_MEDIA_CODEC_TYPE;
+
+	switch (sbc->channels) {
+	case 1:
+		v = 8;
+		break;
+	case 2:
+	default:
+		v = 2;
+		break;
+	}
+	s_config.codec_elements.sbc_elements.channel_mode = v;
 
-        switch(sbc->rate) {
-        case 16000:
-                v = 8;
-                break;
-        case 32000:
-                v = 4;
-                break;
-        case 48000:
-                v = 1;
-                break;
-        case 44100:
-        default:
-                v = 2; 
-                break;
-        }
-        s_config.codec_elements.sbc_elements.frequency = v;
-        s_config.codec_elements.sbc_elements.allocation_method = 1 << 1;
+	switch (sbc->rate) {
+	case 16000:
+		v = 8;
+		break;
+	case 32000:
+		v = 4;
+		break;
+	case 48000:
+		v = 1;
+		break;
+	case 44100:
+	default:
+		v = 2;
+		break;
+	}
+	s_config.codec_elements.sbc_elements.frequency = v;
+	s_config.codec_elements.sbc_elements.allocation_method = 1 << 1;
 
-        switch(sbc->subbands) {
-        case 4:
-                v = 2;
-                break;
-        case 8:
-        default:
-                v = 1;
-                break;
-        }
-        s_config.codec_elements.sbc_elements.subbands = v;
+	switch (sbc->subbands) {
+	case 4:
+		v = 2;
+		break;
+	case 8:
+	default:
+		v = 1;
+		break;
+	}
+	s_config.codec_elements.sbc_elements.subbands = v;
 
-        switch(sbc->blocks) {
-        case 4:
-                v = 8;
-                break;
-        case 8:
-                v = 4;
-                break;
-        case 12:
-                v = 2;
-                break;
-        case 16:
-        default:
-                v = 1;
-                break;
-        }
-        s_config.codec_elements.sbc_elements.block_length = v;
-        s_config.codec_elements.sbc_elements.min_bitpool = cap_resp.codec_elements.sbc_elements.min_bitpool;
-        s_config.codec_elements.sbc_elements.max_bitpool = cap_resp.codec_elements.sbc_elements.max_bitpool;
+	switch (sbc->blocks) {
+	case 4:
+		v = 8;
+		break;
+	case 8:
+		v = 4;
+		break;
+	case 12:
+		v = 2;
+		break;
+	case 16:
+	default:
+		v = 1;
+		break;
+	}
+	s_config.codec_elements.sbc_elements.block_length = v;
+	s_config.codec_elements.sbc_elements.min_bitpool = cap_resp.codec_elements.sbc_elements.min_bitpool;
+	s_config.codec_elements.sbc_elements.max_bitpool = cap_resp.codec_elements.sbc_elements.max_bitpool;
 
-        if (!(cap_resp.codec_elements.sbc_elements.channel_mode & s_config.codec_elements.sbc_elements.channel_mode)) {
-                DBG("headset does not support this channel mode");
-        }
+	if (!(cap_resp.codec_elements.sbc_elements.channel_mode & s_config.codec_elements.sbc_elements.channel_mode)) {
+		DBG("headset does not support this channel mode");
+	}
 
-        if (!(cap_resp.codec_elements.sbc_elements.frequency & s_config.codec_elements.sbc_elements.frequency)) {
-                DBG("headset does not support this frequency");
-        }
+	if (!(cap_resp.codec_elements.sbc_elements.frequency & s_config.codec_elements.sbc_elements.frequency)) {
+		DBG("headset does not support this frequency");
+	}
 
-        if (!(cap_resp.codec_elements.sbc_elements.allocation_method & s_config.codec_elements.sbc_elements.allocation_method)) {
-                DBG("headset does not support this allocation_method");
-        }
+	if (!(cap_resp.codec_elements.sbc_elements.allocation_method & s_config.codec_elements.sbc_elements.allocation_method)) {
+		DBG("headset does not support this allocation_method");
+	}
 
-        if (!(cap_resp.codec_elements.sbc_elements.subbands & s_config.codec_elements.sbc_elements.subbands)) {
-                DBG("headset does not support this subbands setting");
-        }
+	if (!(cap_resp.codec_elements.sbc_elements.subbands & s_config.codec_elements.sbc_elements.subbands)) {
+		DBG("headset does not support this subbands setting");
+	}
 
-        if (write(s, &s_config, sizeof(s_config)) != sizeof(s_config)) {
-                DBG("couldn't set config seid = %d", seid);
-                return (-1);
-        }
+	if (write(s, &s_config, sizeof(s_config)) != sizeof(s_config)) {
+		DBG("couldn't set config seid = %d", seid);
+		return (-1);
+	}
 
-        size = read(s, &s_resp, sizeof(s_resp));
-        DBG("Got Set Configurations Response (%d bytes:msgtype=%d,pkttype=%d,lbl=%d,sig=%d,rfa=%d)", 
-                size,
-                s_resp.header.message_type,
-                s_resp.header.packet_type,
-                s_resp.header.transaction_label,
-                s_resp.header.signal_id,
-                s_resp.header.rfa0);
-        
-        memset(&open_stream, 0, sizeof(open_stream));
-        init_request(&open_stream.header, AVDTP_OPEN);
-        open_stream.acp_seid = seid;
-
-        if (write(s, &open_stream, sizeof(open_stream)) != sizeof(open_stream)) {
-                DBG("Couldn't open stream SEID = %d", seid);
-                return (-1);
-        }
+	size = read(s, &s_resp, sizeof(s_resp));
+	DBG("Got Set Configurations Response (%d bytes:msgtype=%d,pkttype=%d,lbl=%d,sig=%d,rfa=%d)",
+	    size, s_resp.header.message_type, s_resp.header.packet_type, s_resp.header.transaction_label, s_resp.header.signal_id, s_resp.header.rfa0);
+
+	memset(&open_stream, 0, sizeof(open_stream));
+	init_request(&open_stream.header, AVDTP_OPEN);
+	open_stream.acp_seid = seid;
+
+	if (write(s, &open_stream, sizeof(open_stream)) != sizeof(open_stream)) {
+		DBG("Couldn't open stream SEID = %d", seid);
+		return (-1);
+	}
 
-        if (read(s, &open_resp, sizeof(open_resp)) < sizeof(open_resp) - 1 ||
-                        open_resp.header.message_type == MESSAGE_TYPE_REJECT) {
-                DBG("Didn't receive open response confirm for SEID = %d", seid);
-                return (-1);
-        }
+	if (read(s, &open_resp, sizeof(open_resp)) < sizeof(open_resp) - 1 || open_resp.header.message_type == MESSAGE_TYPE_REJECT) {
+		DBG("Didn't receive open response confirm for SEID = %d", seid);
+		return (-1);
+	}
 
-        *psm = 25;
-        return 0;
+	*psm = 25;
+	return 0;
 }
 
 int test_sdp(dst)
 {
 	int result = 0;
-	
+
 	return result;
 }
 
 // Connecting on PSM 25
-int do_connect(bdaddr_t *src, bdaddr_t *dst, unsigned short psm, uint16_t *mtu)
+int do_connect(bdaddr_t * src, bdaddr_t * dst, unsigned short psm, uint16_t * mtu)
 {
-        struct sockaddr_l2 addr;
-        struct l2cap_options opts;
-        int sk;
-        unsigned int opt;
-        int tries;
-
-        sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
-        if (sk < 0) {
-                DBG( "Can't create socket. %s(%d)",
-                        strerror(errno), errno);
-                return -1;
-        }
-
-        // Set connection timeout
-        struct timeval t = { 3, 0 };
-        setsockopt( sk, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t));
-        setsockopt( sk, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
-
-        memset(&addr, 0, sizeof(addr));
-        addr.l2_family = AF_BLUETOOTH;
-        bacpy(&addr.l2_bdaddr, src);
-        if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-                DBG( "Can't bind socket. %s(%d)",
-                                                strerror(errno), errno);
-                return -1;
-        }
-
-        /* Get default options */
-        opt = sizeof(opts);
-        if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &opt) < 0) {
-                DBG( "Can't get default L2CAP options. %s(%d)",
-                                                strerror(errno), errno);
-                return -1;
-        }
+	struct sockaddr_l2 addr;
+	struct l2cap_options opts;
+	int sk;
+	unsigned int opt;
+	int tries;
+
+	sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
+	if (sk < 0) {
+		DBG("Can't create socket. %s(%d)", strerror(errno), errno);
+		return -1;
+	}
+	// Set connection timeout
+	struct timeval t = { 3, 0 };
+	setsockopt(sk, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t));
+	setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
+
+	memset(&addr, 0, sizeof(addr));
+	addr.l2_family = AF_BLUETOOTH;
+	bacpy(&addr.l2_bdaddr, src);
+	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		DBG("Can't bind socket. %s(%d)", strerror(errno), errno);
+		return -1;
+	}
 
-        /* Set new options */
-        if(mtu && *mtu) {
-                opts.omtu = *mtu;
-                //opts.imtu = *mtu;
-        }
-        if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, opt) < 0) {
-                DBG( "Can't set L2CAP options. %s(%d)",
-                                                strerror(errno), errno);
-                return -1;
-        }
+	/* Get default options */
+	opt = sizeof(opts);
+	if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &opt) < 0) {
+		DBG("Can't get default L2CAP options. %s(%d)", strerror(errno), errno);
+		return -1;
+	}
 
-        memset(&addr, 0, sizeof(addr));
-        addr.l2_family = AF_BLUETOOTH;
-        bacpy(&addr.l2_bdaddr, dst);
-        addr.l2_psm = htobs(psm);
-
-        tries = 0;
-        while (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-                DBG("Can't connect to %s on psm %d. %s(%d)",
-                                batostr(&addr.l2_bdaddr), psm, strerror(errno), errno);
-                if(++tries > NBSDPRETRIESMAX) {
-                        close(sk);
-                        return -1;
-                }
-                sleep(1);
-        }
-        opt = sizeof(opts);
-        if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &opt) < 0) {
-                DBG( "Can't get L2CAP options. %s(%d)",
-                                                strerror(errno), errno);
-                close(sk);
-                return -1;
-        }
+	/* Set new options */
+	if (mtu && *mtu) {
+		opts.omtu = *mtu;
+		//opts.imtu = *mtu;
+	}
+	if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, opt) < 0) {
+		DBG("Can't set L2CAP options. %s(%d)", strerror(errno), errno);
+		return -1;
+	}
 
-        //DBG( "Connected psm=%d sk=%d [imtu %d, omtu %d, flush_to %d]", psm, sk, opts.imtu, opts.omtu, opts.flush_to);
+	memset(&addr, 0, sizeof(addr));
+	addr.l2_family = AF_BLUETOOTH;
+	bacpy(&addr.l2_bdaddr, dst);
+	addr.l2_psm = htobs(psm);
+
+	tries = 0;
+	while (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		DBG("Can't connect to %s on psm %d. %s(%d)", batostr(&addr.l2_bdaddr), psm, strerror(errno), errno);
+		if (++tries > NBSDPRETRIESMAX) {
+			close(sk);
+			return -1;
+		}
+		sleep(1);
+	}
+	opt = sizeof(opts);
+	if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &opt) < 0) {
+		DBG("Can't get L2CAP options. %s(%d)", strerror(errno), errno);
+		close(sk);
+		return -1;
+	}
+	//DBG( "Connected psm=%d sk=%d [imtu %d, omtu %d, flush_to %d]", psm, sk, opts.imtu, opts.omtu, opts.flush_to);
 
-        if (mtu)
-                *mtu = opts.omtu;
+	if (mtu)
+		*mtu = opts.omtu;
 
-        return sk;
+	return sk;
 }
 
 // Detect whether A2DP Sink is present at the destination or not
-int detect_a2dp(bdaddr_t *src, bdaddr_t *dst, unsigned short *psm, unsigned long *flags)
+int detect_a2dp(bdaddr_t * src, bdaddr_t * dst, unsigned short *psm, unsigned long *flags)
 {
-        sdp_session_t *sess;
-        sdp_list_t *attrid, *search, *seq, *next;
-        sdp_data_t *pdlist;
-        uuid_t group;
-        uint32_t range = 0x0000ffff;
-        int err;
-        int tries;
+	sdp_session_t *sess;
+	sdp_list_t *attrid, *search, *seq, *next;
+	sdp_data_t *pdlist;
+	uuid_t group;
+	uint32_t range = 0x0000ffff;
+	int err;
+	int tries;
 
 	// Try to connect an L2CAP socket to the sdp psm with short timeout for user interaction
 	int tmpsk = do_connect(src, dst, 1, NULL);
-	if(tmpsk>0)
-	{
+	if (tmpsk > 0) {
 		close(tmpsk);
-	}
-	else
-	{
-                DBG( "Warning: failed to connect to SDP server");
+	} else {
+		DBG("Warning: failed to connect to SDP server");
 		return -1;
 	}
 
-        tries = 0;
-        while(!(sess = sdp_connect(src, dst, SDP_RETRY_IF_BUSY))) {
-                DBG("retrying sdp connect: %s", strerror(errno));
-                if(++tries > NBSDPRETRIESMAX) {
-                        break;
-			}
-                sleep(1);
-        }
-        if (!sess) {
-                DBG( "Warning: failed to connect to SDP server");
-                if(psm) *psm = 25;
-                if(flags) *flags = 0;
-                return 0;
-        }
-
-        /* 0x1108->all? 0x1101->rf sink 0x111e->handsfree 0x1108->headset */
-        sdp_uuid16_create(&group, 0x110d);
-        search = sdp_list_append(0, &group);
-        attrid = sdp_list_append(0, &range);
-        err = sdp_service_search_attr_req(sess, search,
-                                        SDP_ATTR_REQ_RANGE, attrid, &seq);
-        sdp_list_free(search, 0);
-        sdp_list_free(attrid, 0);
-
-        if (err) {
-                DBG( "Service Search failed: %s", strerror(errno));
-                sdp_close(sess);
-                return -1;
-        }
-
-        for (; seq; seq = next) {
-                sdp_record_t *rec = (sdp_record_t *) seq->data;
+	tries = 0;
+	while (!(sess = sdp_connect(src, dst, SDP_RETRY_IF_BUSY))) {
+		DBG("retrying sdp connect: %s", strerror(errno));
+		if (++tries > NBSDPRETRIESMAX) {
+			break;
+		}
+		sleep(1);
+	}
+	if (!sess) {
+		DBG("Warning: failed to connect to SDP server");
+		if (psm)
+			*psm = 25;
+		if (flags)
+			*flags = 0;
+		return 0;
+	}
 
-                DBG( "Found A2DP Sink");
-                if (psm)
-                        *psm = 25;
-
-                next = seq->next;
-                free(seq);
-                sdp_record_free(rec);
-        }
+	/* 0x1108->all? 0x1101->rf sink 0x111e->handsfree 0x1108->headset */
+	sdp_uuid16_create(&group, 0x110d);
+	search = sdp_list_append(0, &group);
+	attrid = sdp_list_append(0, &range);
+	err = sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq);
+	sdp_list_free(search, 0);
+	sdp_list_free(attrid, 0);
+
+	if (err) {
+		DBG("Service Search failed: %s", strerror(errno));
+		sdp_close(sess);
+		return -1;
+	}
 
-        sdp_uuid16_create(&group, PNP_INFO_SVCLASS_ID);
-        search = sdp_list_append(0, &group);
-        attrid = sdp_list_append(0, &range);
-        err = sdp_service_search_attr_req(sess, search,
-                                        SDP_ATTR_REQ_RANGE, attrid, &seq);
-        sdp_list_free(search, 0);
-        sdp_list_free(attrid, 0);
-
-        if (err)
-                goto done;
-
-        if (flags)
-                *flags = 0;
-
-        for (; seq; seq = next) {
-                sdp_record_t *rec = (sdp_record_t *) seq->data;
-                uint16_t vendor, product, version;
-
-                pdlist = sdp_data_get(rec, 0x0201);
-                vendor = pdlist ? pdlist->val.uint16 : 0x0000;
-
-                pdlist = sdp_data_get(rec, 0x0202);
-                product = pdlist ? pdlist->val.uint16 : 0x0000;
-
-                pdlist = sdp_data_get(rec, 0x0203);
-                version = pdlist ? pdlist->val.uint16 : 0x0000;
-
-                DBG( "Product ID %04x:%04x:%04x", vendor, product, version);
-
-                if (vendor == 0x1310 && product == 0x0100 && version == 0x0104) {
-                        DBG( "Enabling GCT media payload workaround");
-                        if (flags)
-                                *flags |= NONSPECAUDIO;
-                }
+	for (; seq; seq = next) {
+		sdp_record_t *rec = (sdp_record_t *) seq->data;
 
-                next = seq->next;
-                free(seq);
-                sdp_record_free(rec);
-        }
+		DBG("Found A2DP Sink");
+		if (psm)
+			*psm = 25;
+
+		next = seq->next;
+		free(seq);
+		sdp_record_free(rec);
+	}
 
-done:
-        sdp_close(sess);
-        return 0;
-}
-
-int connect_stream(bdaddr_t *src, bdaddr_t *dst, int *cmdfd_return, sbc_t *sbc, int* seid_return, int* omtu)
-{
-        int cmdfd=-1;
-        struct sepd_req discover_req;
-        struct sepd_resp discover_resp;
-        struct stream_cmd start_stream;
-        struct start_stream_rsp start_resp;
-        int seid, nb_seid;
-        int size;
-        int i;
-        unsigned short psm_cmd,psm_stream=25;
-        unsigned long flags = 0;
-        int streamfd = -1;
-        uint16_t mtu = 0;
-        int tries, res;
-
-        if (detect_a2dp(src, dst, &psm_cmd, &flags) < 0) {
-                DBG( "could not find A2DP services on device %s", batostr(dst));
-                return -1;
-        }
-        else {
-                DBG( "Found A2DP Sink at the destination (psm_cmd=%d)", psm_cmd);
-        }
+	sdp_uuid16_create(&group, PNP_INFO_SVCLASS_ID);
+	search = sdp_list_append(0, &group);
+	attrid = sdp_list_append(0, &range);
+	err = sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq);
+	sdp_list_free(search, 0);
+	sdp_list_free(attrid, 0);
+
+	if (err)
+		goto done;
+
+	if (flags)
+		*flags = 0;
+
+	for (; seq; seq = next) {
+		sdp_record_t *rec = (sdp_record_t *) seq->data;
+		uint16_t vendor, product, version;
+
+		pdlist = sdp_data_get(rec, 0x0201);
+		vendor = pdlist ? pdlist->val.uint16 : 0x0000;
+
+		pdlist = sdp_data_get(rec, 0x0202);
+		product = pdlist ? pdlist->val.uint16 : 0x0000;
+
+		pdlist = sdp_data_get(rec, 0x0203);
+		version = pdlist ? pdlist->val.uint16 : 0x0000;
+
+		DBG("Product ID %04x:%04x:%04x", vendor, product, version);
+
+		if (vendor == 0x1310 && product == 0x0100 && version == 0x0104) {
+			DBG("Enabling GCT media payload workaround");
+			if (flags)
+				*flags |= NONSPECAUDIO;
+		}
+
+		next = seq->next;
+		free(seq);
+		sdp_record_free(rec);
+	}
 
-        psm_cmd=25;	
-        cmdfd = do_connect(src, dst, psm_cmd, &mtu);
-        if (cmdfd < 0) {
-                DBG( "cannot open psm_cmd = %d", psm_cmd);
-                return -1;
-        }
+      done:
+	sdp_close(sess);
+	return 0;
+}
+
+int connect_stream(bdaddr_t * src, bdaddr_t * dst, int *cmdfd_return, sbc_t * sbc, int *seid_return, int *omtu)
+{
+	int cmdfd = -1;
+	struct sepd_req discover_req;
+	struct sepd_resp discover_resp;
+	struct stream_cmd start_stream;
+	struct start_stream_rsp start_resp;
+	int seid, nb_seid;
+	int size;
+	int i;
+	unsigned short psm_cmd, psm_stream = 25;
+	unsigned long flags = 0;
+	int streamfd = -1;
+	uint16_t mtu = 0;
+	int tries, res;
 
-        // avdt_discover_req
-        memset(&discover_req, 0, sizeof(discover_req));
-        init_request(&discover_req.header, AVDTP_DISCOVER);
-
-        res=write(cmdfd, &discover_req, sizeof(discover_req));
-        if (res != sizeof(discover_req)) {
-                DBG("couldn't send avdtp_discover (res=%d)", res);
-                close(cmdfd);
-                return -1;
-        }
-        else {
-                DBG("Sent the Stream End Point Discovery Command");
-        }
-        tries = 0;
-        memset(&discover_resp, 0, sizeof(discover_resp));
+	if (detect_a2dp(src, dst, &psm_cmd, &flags) < 0) {
+		DBG("could not find A2DP services on device %s", batostr(dst));
+		return -1;
+	} else {
+		DBG("Found A2DP Sink at the destination (psm_cmd=%d)", psm_cmd);
+	}
 
-        // SONORIX sends us a discover signal we should answer but we will discard
-        while(tries<10)
-        {
-                size=a2dp_handle_avdtp_message(NULL, cmdfd, &discover_req.header, &discover_resp.header, sizeof(discover_resp));
-                if(size>0)
-                {
-                        // Answer to what we send
-                        break;
-                }
-                else
-                {
-                        // Not answer
-                        usleep(100);
-                        tries++;
-                }
-        }
+	psm_cmd = 25;
+	cmdfd = do_connect(src, dst, psm_cmd, &mtu);
+	if (cmdfd < 0) {
+		DBG("cannot open psm_cmd = %d", psm_cmd);
+		return -1;
+	}
+	// avdt_discover_req
+	memset(&discover_req, 0, sizeof(discover_req));
+	init_request(&discover_req.header, AVDTP_DISCOVER);
+
+	res = write(cmdfd, &discover_req, sizeof(discover_req));
+	if (res != sizeof(discover_req)) {
+		DBG("couldn't send avdtp_discover (res=%d)", res);
+		close(cmdfd);
+		return -1;
+	} else {
+		DBG("Sent the Stream End Point Discovery Command");
+	}
+	tries = 0;
+	memset(&discover_resp, 0, sizeof(discover_resp));
 
-        if (size > sizeof(discover_resp.header))
-        {
-                DBG("Got a Stream End Point Discovery (%d bytes) Response (msgtype=%d,pkttype=%d,lbl=%d,sig=%d,rfa=%d)", 
-                size,
-                discover_resp.header.message_type,
-                discover_resp.header.packet_type,
-                discover_resp.header.transaction_label,
-                discover_resp.header.signal_id,
-                discover_resp.header.rfa0);
-                for(i=0; i<size; i++)
-                        printf("%02X", (int)(*(((char*)&discover_resp)+i)));
-                printf("\n");
-        }
-        else
-        {
-                DBG("couldn't get avdtp_discover (size=%d, min=%d, max=%d)", size, sizeof(discover_resp.header), sizeof(discover_resp));
-                close(cmdfd);
-                return -1;
-        }
+	// SONORIX sends us a discover signal we should answer but we will discard
+	while (tries < 10) {
+		size = a2dp_handle_avdtp_message(NULL, cmdfd, &discover_req.header, &discover_resp.header, sizeof(discover_resp));
+		if (size > 0) {
+			// Answer to what we send
+			break;
+		} else {
+			// Not answer
+			usleep(100);
+			tries++;
+		}
+	}
 
-        seid = -1;
-        nb_seid = (size-sizeof(discover_resp.header))/sizeof(struct acp_seid_info);
+	if (size > sizeof(discover_resp.header)) {
+		DBG("Got a Stream End Point Discovery (%d bytes) Response (msgtype=%d,pkttype=%d,lbl=%d,sig=%d,rfa=%d)",
+		    size, discover_resp.header.message_type, discover_resp.header.packet_type, discover_resp.header.transaction_label, discover_resp.header.signal_id, discover_resp.header.rfa0);
+		for (i = 0; i < size; i++)
+			printf("%02X", (int) (*(((char *) &discover_resp) + i)));
+		printf("\n");
+	} else {
+		DBG("couldn't get avdtp_discover (size=%d, min=%d, max=%d)", size, sizeof(discover_resp.header), sizeof(discover_resp));
+		close(cmdfd);
+		return -1;
+	}
 
-        DBG("received %d capabilities", nb_seid);
+	seid = -1;
+	nb_seid = (size - sizeof(discover_resp.header)) / sizeof(struct acp_seid_info);
 
-        for(i=0; i < nb_seid; i++)
-        {
-                if (process_seid(cmdfd, &discover_resp.infos[i], &psm_stream, sbc) == 0)
-                {
-                        seid = discover_resp.infos[i].acp_seid;
-                        break;
-                }
-        }
+	DBG("received %d capabilities", nb_seid);
 
-        if(seid == -1) {
-                //We have not found the seid that we want
-                DBG("couldn't locate the correct seid");
-                return -1;
-        }
+	for (i = 0; i < nb_seid; i++) {
+		if (process_seid(cmdfd, &discover_resp.infos[i], &psm_stream, sbc) == 0) {
+			seid = discover_resp.infos[i].acp_seid;
+			break;
+		}
+	}
 
-        // open the stream
-        streamfd = do_connect(src, dst, psm_stream, &mtu);
-        if (streamfd < 0) {
-                DBG("cannot open psm_stream = %d", psm_stream);
-                return -1;
-        }
+	if (seid == -1) {
+		//We have not found the seid that we want
+		DBG("couldn't locate the correct seid");
+		return -1;
+	}
+	// open the stream
+	streamfd = do_connect(src, dst, psm_stream, &mtu);
+	if (streamfd < 0) {
+		DBG("cannot open psm_stream = %d", psm_stream);
+		return -1;
+	}
+	// start the stream
 
-        // start the stream
+	memset(&start_stream, 0, sizeof(start_stream));
+	init_request(&start_stream.header, AVDTP_START);
+	start_stream.acp_seid = seid;
+
+	if (write(cmdfd, &start_stream, sizeof(start_stream)) != sizeof(start_stream)) {
+		DBG("couldn't send start_stream");
+		close(streamfd);
+		close(cmdfd);
+		return -1;
+	}
 
-        memset(&start_stream, 0, sizeof(start_stream));
-        init_request(&start_stream.header, AVDTP_START);
-        start_stream.acp_seid = seid;
-
-        if (write(cmdfd, &start_stream, sizeof(start_stream)) != sizeof(start_stream)) {
-                DBG("couldn't send start_stream");
-                close(streamfd);
-                close(cmdfd);
-                return -1;
-        }
+	DBG("Sent stream start(seid=%d)", seid);
 
-        DBG("Sent stream start(seid=%d)", seid);
+	if (read(cmdfd, &start_resp, sizeof(start_resp)) < sizeof(start_resp) - 2 || start_resp.header.message_type == MESSAGE_TYPE_REJECT) {
+		DBG("didn't receive start_resp confirm for seid = %d", seid);
+		close(streamfd);
+		close(cmdfd);
+		return (-1);
+	}
 
-        if (read(cmdfd, &start_resp, sizeof(start_resp)) < sizeof(start_resp) - 2 ||start_resp.header.message_type == MESSAGE_TYPE_REJECT) {
-                DBG("didn't receive start_resp confirm for seid = %d", seid);
-                close(streamfd);
-                close(cmdfd);
-                return (-1);
-        }
+	DBG("Got start stream confirm");
 
-        DBG("Got start stream confirm");
+	*omtu = A2DPMAXIMUMTRANSFERUNITSIZE;	//mtu;
+	*seid_return = seid;
+	*cmdfd_return = cmdfd;
+	return streamfd;
+}
+
+typedef struct snd_pcm_a2dp {
+	bdaddr_t src;
+	bdaddr_t dst;
+	int sk;
+	int control_sk;
+	sbc_t sbc;
+	unsigned char buf[1024];	// contain sbc encoded data, incrementally filled
+	unsigned int len;	// number of valid bytes in buf
+	unsigned int frame_bytes;	// fixed when initializing
+
+	char bufe[BUFS];	// temporary encoding buffer
+	int lenbufe;		//=0;
+
+	time_t timestamp;	//=0;
+	uint16_t seq_num;	//=1;
+	int frame_count;	//=0; // Number of sbc frames in one AVDTP packet
+
+	int mtu;		//=A2DPMAXIMUMTRANSFERUNITSIZE
+	int seid;
+
+	// Used to control stream from headset
+	int stop_writing;	// = 0;
+	int pause_writing;	// = 0;
+	pthread_t hListenThread;
 
-        *omtu = A2DPMAXIMUMTRANSFERUNITSIZE; //mtu;
-        *seid_return = seid;
-        *cmdfd_return = cmdfd;
-        return streamfd;
-}
-
-typedef struct snd_pcm_a2dp
-{
-        bdaddr_t src;
-        bdaddr_t dst;
-        int sk;
-        int control_sk;
-        sbc_t sbc;
-        unsigned char buf[1024]; // contain sbc encoded data, incrementally filled
-        unsigned int len; // number of valid bytes in buf
-        unsigned int frame_bytes; // fixed when initializing
-        
-        char bufe[BUFS]; // temporary encoding buffer
-        int lenbufe;//=0;
- 
-        time_t timestamp;//=0;
-        uint16_t seq_num;//=1;
-        int frame_count;//=0; // Number of sbc frames in one AVDTP packet
- 
-        int mtu;//=A2DPMAXIMUMTRANSFERUNITSIZE
-        int seid;
-
-        // Used to control stream from headset
-        int stop_writing;// = 0;
-        int pause_writing;// = 0;
-        pthread_t hListenThread;
-        
 } snd_pcm_a2dp_t;
 
 // We have pcm data to send through bluetooth
-int a2dp_transfer_raw(LPA2DP a2dp, const char* pcm_buffer, int pcm_buffer_size)
+int a2dp_transfer_raw(LPA2DP a2dp, const char *pcm_buffer, int pcm_buffer_size)
 {
-        // No error
-        int result = 0;
-        struct media_packet_header packet_header;
-        struct media_payload_header payload_header;
-        int codesize,datatoread;
-        int written;
-
-        // Check parameter
-        if(a2dp==0 || pcm_buffer==0 || pcm_buffer_size==0) return EINVAL;
-
-        // How much data can be encoded by sbc at a time?
-        // 16 bits * 2 channels * 16 blocks * 8 subbands = 4096bits = 512 o
-        codesize=a2dp->sbc.subbands*a2dp->sbc.blocks*a2dp->sbc.channels*2;
-        // 44 bitpool?
-        //codesize=a2dp->sbc.bitpool*a2dp->sbc.subbands*a2dp->sbc.blocks/8;
-        datatoread=min(codesize,pcm_buffer_size);
-
-        // Enqueue data in bufe
-        if(a2dp->lenbufe+datatoread < BUFS)
-        {
-                // Append data to bufe, for sbc encoding
-                memcpy_changeendian(a2dp->bufe+a2dp->lenbufe, pcm_buffer, datatoread);
-                a2dp->lenbufe+=datatoread;
-        }
-        else
-        {
-                datatoread=0;
-        }
-
-
-        // If bufe is full, encode
-        if(a2dp->lenbufe>=codesize)
-        {
-                // Enough data to encode (sbc wants 1k blocks)
-                int encoded;
-                encoded = sbc_encode(&(a2dp->sbc), a2dp->bufe, codesize); //encode
-
-                if (encoded <= 0)
-                        return encoded;
-
-                memmove(a2dp->bufe, a2dp->bufe + encoded, a2dp->lenbufe - encoded); // Shift the bufe
-                a2dp->lenbufe -= encoded;
-
-                // Send data through bluetooth
-                if(a2dp->len + a2dp->sbc.len >= a2dp->mtu)
-                {
-                        // time to prepare and send the packet
-                        memset(&payload_header, 0, sizeof(payload_header));
-                        memset(&packet_header, 0, sizeof(packet_header));
-                        payload_header.frame_count=a2dp->frame_count;
-                        packet_header.v = 2;
-                        packet_header.pt = 1;
-                        packet_header.cc = 0;
-                        packet_header.sequence_number = htons(a2dp->seq_num);
-                        packet_header.timestamp = htonl(a2dp->timestamp);
-                        packet_header.ssrc = htonl(1);
-
-                        a2dp->timestamp += (a2dp->sbc.blocks+1)*4 * (a2dp->sbc.subbands+1)*4;
-                        memcpy(a2dp->buf, &packet_header, sizeof(packet_header));
-                        memcpy(a2dp->buf + sizeof(packet_header), &payload_header, sizeof(payload_header));
-                        if(a2dp->sk>0)
-                        {
-                                // Check if data are to be read
-                                // Not seen a device showing this yet
-                                fd_set readfds;
-                                struct timeval zero_timeout = {0,0};
-                                FD_ZERO(&readfds);
-                                FD_SET(a2dp->sk, &readfds);
-                                int iselect=select(1, &readfds, NULL, NULL, &zero_timeout);
-                                if(iselect>0)
-                                {
-                                        if(FD_ISSET(a2dp->sk, &readfds))
-                                        {
-                                                a2dp_handle_avdtp_message(a2dp, a2dp->sk, NULL, NULL, 0);
-                                        }
-                                }
-                                // Pause?
-                                // The value 0 have never been tested
-                                // However, we may safely simulate a failed write
-                                if(!a2dp->pause_writing)
-                                {
-                                        // Send our data
-                                        if((written = write(a2dp->sk,a2dp->buf,a2dp->len)) != a2dp->len)
-                                        {
-                                                // Error while sending data
-                                                DBG("Wrote %d not %d bytes; (errno=%d:%s)", written, a2dp->len, errno,
-                                                        strerror(errno));
-                                                result = written;
-                                        }
-                                        result = written;
-                                }
-                                else
-                                {
-                                        // Make the upper layer believe we sent data
-                                        result = a2dp->len;
-                                }
-                        }
+	// No error
+	int result = 0;
+	struct media_packet_header packet_header;
+	struct media_payload_header payload_header;
+	int codesize, datatoread;
+	int written;
+
+	// Check parameter
+	if (a2dp == 0 || pcm_buffer == 0 || pcm_buffer_size == 0)
+		return EINVAL;
+
+	// How much data can be encoded by sbc at a time?
+	// 16 bits * 2 channels * 16 blocks * 8 subbands = 4096bits = 512 o
+	codesize = a2dp->sbc.subbands * a2dp->sbc.blocks * a2dp->sbc.channels * 2;
+	// 44 bitpool?
+	//codesize=a2dp->sbc.bitpool*a2dp->sbc.subbands*a2dp->sbc.blocks/8;
+	datatoread = min(codesize, pcm_buffer_size);
+
+	// Enqueue data in bufe
+	if (a2dp->lenbufe + datatoread < BUFS) {
+		// Append data to bufe, for sbc encoding
+		memcpy_changeendian(a2dp->bufe + a2dp->lenbufe, pcm_buffer, datatoread);
+		a2dp->lenbufe += datatoread;
+	} else {
+		datatoread = 0;
+	}
 
-                        // Reset buffer of data to send
-                        a2dp->len = sizeof(struct media_packet_header)+sizeof(struct media_payload_header);
-                        a2dp->frame_count=0;
-                        a2dp->seq_num++;
-                }
 
-                // Append sbc encoded data to buf, until buf reaches A2DPMAXIMUMTRANSFERUNITSIZE to send
-                a2dp->frame_count++;
-                memcpy(a2dp->buf + a2dp->len, a2dp->sbc.data, a2dp->sbc.len);
-                a2dp->len+=a2dp->sbc.len;
-        }
+	// If bufe is full, encode
+	if (a2dp->lenbufe >= codesize) {
+		// Enough data to encode (sbc wants 1k blocks)
+		int encoded;
+		encoded = sbc_encode(&(a2dp->sbc), a2dp->bufe, codesize);	//encode
+
+		if (encoded <= 0)
+			return encoded;
+
+		memmove(a2dp->bufe, a2dp->bufe + encoded, a2dp->lenbufe - encoded);	// Shift the bufe
+		a2dp->lenbufe -= encoded;
+
+		// Send data through bluetooth
+		if (a2dp->len + a2dp->sbc.len >= a2dp->mtu) {
+			// time to prepare and send the packet
+			memset(&payload_header, 0, sizeof(payload_header));
+			memset(&packet_header, 0, sizeof(packet_header));
+			payload_header.frame_count = a2dp->frame_count;
+			packet_header.v = 2;
+			packet_header.pt = 1;
+			packet_header.cc = 0;
+			packet_header.sequence_number = htons(a2dp->seq_num);
+			packet_header.timestamp = htonl(a2dp->timestamp);
+			packet_header.ssrc = htonl(1);
+
+			a2dp->timestamp += (a2dp->sbc.blocks + 1) * 4 * (a2dp->sbc.subbands + 1) * 4;
+			memcpy(a2dp->buf, &packet_header, sizeof(packet_header));
+			memcpy(a2dp->buf + sizeof(packet_header), &payload_header, sizeof(payload_header));
+			if (a2dp->sk > 0) {
+				// Check if data are to be read
+				// Not seen a device showing this yet
+				fd_set readfds;
+				struct timeval zero_timeout = { 0, 0 };
+				FD_ZERO(&readfds);
+				FD_SET(a2dp->sk, &readfds);
+				int iselect = select(1, &readfds, NULL, NULL, &zero_timeout);
+				if (iselect > 0) {
+					if (FD_ISSET(a2dp->sk, &readfds)) {
+						a2dp_handle_avdtp_message(a2dp, a2dp->sk, NULL, NULL, 0);
+					}
+				}
+				// Pause?
+				// The value 0 have never been tested
+				// However, we may safely simulate a failed write
+				if (!a2dp->pause_writing) {
+					// Send our data
+					if ((written = write(a2dp->sk, a2dp->buf, a2dp->len)) != a2dp->len) {
+						// Error while sending data
+						DBG("Wrote %d not %d bytes; (errno=%d:%s)", written, a2dp->len, errno, strerror(errno));
+						result = written;
+					}
+					result = written;
+				} else {
+					// Make the upper layer believe we sent data
+					result = a2dp->len;
+				}
+			}
+			// Reset buffer of data to send
+			a2dp->len = sizeof(struct media_packet_header) + sizeof(struct media_payload_header);
+			a2dp->frame_count = 0;
+			a2dp->seq_num++;
+		}
+		// Append sbc encoded data to buf, until buf reaches A2DPMAXIMUMTRANSFERUNITSIZE to send
+		a2dp->frame_count++;
+		memcpy(a2dp->buf + a2dp->len, a2dp->sbc.data, a2dp->sbc.len);
+		a2dp->len += a2dp->sbc.len;
+	}
 
-        return result;
+	return result;
 }
 
-static void init_response(struct avdtp_header * header, int response_type)
+static void init_response(struct avdtp_header *header, int response_type)
 {
-        // leave signal_id and transaction label since we are reusing the request
-        header->packet_type = PACKET_TYPE_SINGLE;
-        header->message_type = response_type;
+	// leave signal_id and transaction label since we are reusing the request
+	header->packet_type = PACKET_TYPE_SINGLE;
+	header->message_type = response_type;
 
-        // clear rfa bits
-        header->rfa0 = 0;
+	// clear rfa bits
+	header->rfa0 = 0;
 }
 
 // monitor the control connection for pause/play signals from headset
 // note this signaling is in the avdtp core; avrcp signaling is different
-static void* listen_thread(void* param)
+static void *listen_thread(void *param)
 {
-        snd_pcm_a2dp_t* a2dp = (snd_pcm_a2dp_t*)param;
+	snd_pcm_a2dp_t *a2dp = (snd_pcm_a2dp_t *) param;
 
-        if(a2dp->control_sk<0) 
-        {
-        	DBG("Listen thread not started [control_sk=%d]", a2dp->control_sk);
+	if (a2dp->control_sk < 0) {
+		DBG("Listen thread not started [control_sk=%d]", a2dp->control_sk);
 		return NULL;
-        }
-
-        DBG("Listen thread running [control_sk=%d]", a2dp->control_sk);
+	}
 
-        // Set a timeout to close thread
-        struct timeval t = { 1, 0 };
-        setsockopt( a2dp->control_sk, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t));
-        setsockopt( a2dp->control_sk, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
+	DBG("Listen thread running [control_sk=%d]", a2dp->control_sk);
 
-        // Loop until end of writing
-        while(!a2dp->stop_writing)
-        {
-                char szBuffer[A2DPMAXIMUMTRANSFERUNITSIZE];
-                struct stream_cmd* cmd = (struct stream_cmd*)szBuffer;
-                if(a2dp_handle_avdtp_message(a2dp, a2dp->control_sk, NULL, NULL, 0)<0)
-                {
-                        // Error
-                        usleep(100*1000);
-                }
-
-                int size = read(a2dp->control_sk, szBuffer, sizeof(szBuffer));
-                if(size>0)
-                {
-                        if(cmd->header.signal_id == AVDTP_SUSPEND)
-                        {
-                                DBG("Received signal AVDTP_SUSPEND(%d) from set", cmd->header.signal_id);
-                                a2dp->pause_writing = 1;
-                        }
-                        else if(cmd->header.signal_id == AVDTP_START)
-                        {
-                                DBG("Received signal AVDTP_START(%d) from set", cmd->header.signal_id);
-                                a2dp->pause_writing = 0;
-                        }
-                        else
-                        {
-                                DBG("Unexpected headset directive %d", cmd->header.signal_id);
-                        }
-                        // ack the command regardless
-                        //FIXME take a shortcut and reuse the command struct (knock one byte off length)
-                        init_response(&cmd->header, MESSAGE_TYPE_ACCEPT);
-                        if (write(a2dp->control_sk, &cmd, sizeof(cmd)-1) != sizeof(cmd)-1)
-                        {
-                                DBG("Couldn't ack %d", cmd->header.signal_id);
-                        }
-                }
-                else
-                {
-                        if(errno!=EAGAIN)
-                                DBG("Error while receiving %d (errno=%d:%s)", size, errno, strerror(errno));
-                        if(errno!=EINTR)
-                                break;
-                }
-        }
+	// Set a timeout to close thread
+	struct timeval t = { 1, 0 };
+	setsockopt(a2dp->control_sk, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t));
+	setsockopt(a2dp->control_sk, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
+
+	// Loop until end of writing
+	while (!a2dp->stop_writing) {
+		char szBuffer[A2DPMAXIMUMTRANSFERUNITSIZE];
+		struct stream_cmd *cmd = (struct stream_cmd *) szBuffer;
+		if (a2dp_handle_avdtp_message(a2dp, a2dp->control_sk, NULL, NULL, 0) < 0) {
+			// Error
+			usleep(100 * 1000);
+		}
+
+		int size = read(a2dp->control_sk, szBuffer, sizeof(szBuffer));
+		if (size > 0) {
+			if (cmd->header.signal_id == AVDTP_SUSPEND) {
+				DBG("Received signal AVDTP_SUSPEND(%d) from set", cmd->header.signal_id);
+				a2dp->pause_writing = 1;
+			} else if (cmd->header.signal_id == AVDTP_START) {
+				DBG("Received signal AVDTP_START(%d) from set", cmd->header.signal_id);
+				a2dp->pause_writing = 0;
+			} else {
+				DBG("Unexpected headset directive %d", cmd->header.signal_id);
+			}
+			// ack the command regardless
+			//FIXME take a shortcut and reuse the command struct (knock one byte off length)
+			init_response(&cmd->header, MESSAGE_TYPE_ACCEPT);
+			if (write(a2dp->control_sk, &cmd, sizeof(cmd) - 1) != sizeof(cmd) - 1) {
+				DBG("Couldn't ack %d", cmd->header.signal_id);
+			}
+		} else {
+			if (errno != EAGAIN)
+				DBG("Error while receiving %d (errno=%d:%s)", size, errno, strerror(errno));
+			if (errno != EINTR)
+				break;
+		}
+	}
 
-        return NULL;
+	return NULL;
 }
 
-int a2dp_connect(snd_pcm_a2dp_t *a2dp)
+int a2dp_connect(snd_pcm_a2dp_t * a2dp)
 {
-        //struct sockaddr_rc addr;
-        //socklen_t len;
-        int sk = -1;
-        int control_sk = -1;
-        errno=0;
-        /*
-        if(a2dp->use_rfcomm) {
-                sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
-                if (sk < 0)
-                        return -errno;
-                
-                memset(&addr, 0, sizeof(addr));
-                addr.rc_family = AF_BLUETOOTH;
-                bacpy(&addr.rc_bdaddr, &a2dp->src);
-                
-                if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-                        close(sk);
-                        return -errno;
-                }
-                
-                memset(&addr, 0, sizeof(addr));
-                addr.rc_family = AF_BLUETOOTH;
-                bacpy(&addr.rc_bdaddr, &a2dp->dst);
-                addr.rc_channel = 1;
-                
-                if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-                        close(sk);
-                        return -errno;
-                }
-
-                memset(&addr, 0, sizeof(addr));
-                len = sizeof(addr);
-                
-                if (getsockname(sk, (struct sockaddr *) &addr, &len) < 0) {
-                        close(sk);
-                        return -errno;
-                }
-
-                bacpy(&a2dp->src, &addr.rc_bdaddr);
+	//struct sockaddr_rc addr;
+	//socklen_t len;
+	int sk = -1;
+	int control_sk = -1;
+	errno = 0;
+	/*
+	   if(a2dp->use_rfcomm) {
+	   sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+	   if (sk < 0)
+	   return -errno;
+
+	   memset(&addr, 0, sizeof(addr));
+	   addr.rc_family = AF_BLUETOOTH;
+	   bacpy(&addr.rc_bdaddr, &a2dp->src);
+
+	   if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+	   close(sk);
+	   return -errno;
+	   }
+
+	   memset(&addr, 0, sizeof(addr));
+	   addr.rc_family = AF_BLUETOOTH;
+	   bacpy(&addr.rc_bdaddr, &a2dp->dst);
+	   addr.rc_channel = 1;
+
+	   if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+	   close(sk);
+	   return -errno;
+	   }
+
+	   memset(&addr, 0, sizeof(addr));
+	   len = sizeof(addr);
+
+	   if (getsockname(sk, (struct sockaddr *) &addr, &len) < 0) {
+	   close(sk);
+	   return -errno;
+	   }
+
+	   bacpy(&a2dp->src, &addr.rc_bdaddr);
+
+	   //fcntl(sk, F_SETFL, fcntl(sk, F_GETFL) | O_NONBLOCK);
+	   } else { */
+	sk = connect_stream(&a2dp->src, &a2dp->dst, &control_sk, &a2dp->sbc, &a2dp->seid, &a2dp->mtu);
+	//}
+
+	a2dp->sk = sk;
+	a2dp->control_sk = control_sk;
+
+	// Start listen thread
+	a2dp->pause_writing = 0;
+	a2dp->stop_writing = 0;
 
-                //fcntl(sk, F_SETFL, fcntl(sk, F_GETFL) | O_NONBLOCK);
-        } else {*/
-                sk = connect_stream(&a2dp->src, &a2dp->dst, &control_sk, &a2dp->sbc, &a2dp->seid, &a2dp->mtu);
-        //}
-
-        a2dp->sk = sk;
-        a2dp->control_sk = control_sk;
-
-        // Start listen thread
-        a2dp->pause_writing = 0;
-        a2dp->stop_writing = 0;
-        
-        if(sk>0)
-        {
+	if (sk > 0) {
 		// Set pthread stack size to decrease unused memory usage
 		pthread_attr_t tattr;
 		size_t size = PTHREAD_STACK_MIN;
 		int ret = pthread_attr_init(&tattr);
 		ret = pthread_attr_setstacksize(&tattr, size);
-		pthread_create(&a2dp->hListenThread, &tattr, listen_thread, (void*)a2dp);
+		pthread_create(&a2dp->hListenThread, &tattr, listen_thread, (void *) a2dp);
 		pthread_attr_destroy(&tattr);
 	}
 
-        return sk;
+	return sk;
 }
 
 snd_pcm_a2dp_t *a2dp_alloc(void)
 {
-        snd_pcm_a2dp_t *a2dp;
-        a2dp = malloc(sizeof(*a2dp));
-        if (!a2dp)
-                return NULL;
-
-        memset(a2dp, 0, sizeof(*a2dp));
-        a2dp->seq_num = 1;
-        a2dp->mtu = A2DPMAXIMUMTRANSFERUNITSIZE;
-        a2dp->len = sizeof(struct media_packet_header)+sizeof(struct media_payload_header);
-
-        sbc_init(&a2dp->sbc, 0L);
-        a2dp->sbc.rate = A2DPD_FRAME_RATE;
-        a2dp->sbc.subbands = 8; // safe default
-        a2dp->sbc.blocks = 16; // safe default
-        a2dp->sbc.bitpool = 32; // recommended value 53, safe default is 32
-        return a2dp;
-}
-
-void a2dp_free(snd_pcm_a2dp_t *a2dp)
-{
-        DBG("");
-        if (a2dp->sk > 0)
-                close(a2dp->sk);
-        if (a2dp->control_sk > 0)
-                close(a2dp->control_sk);
+	snd_pcm_a2dp_t *a2dp;
+	a2dp = malloc(sizeof(*a2dp));
+	if (!a2dp)
+		return NULL;
 
-        sbc_finish(&a2dp->sbc);
+	memset(a2dp, 0, sizeof(*a2dp));
+	a2dp->seq_num = 1;
+	a2dp->mtu = A2DPMAXIMUMTRANSFERUNITSIZE;
+	a2dp->len = sizeof(struct media_packet_header) + sizeof(struct media_payload_header);
+
+	sbc_init(&a2dp->sbc, 0L);
+	a2dp->sbc.rate = A2DPD_FRAME_RATE;
+	a2dp->sbc.subbands = 8;	// safe default
+	a2dp->sbc.blocks = 16;	// safe default
+	a2dp->sbc.bitpool = 32;	// recommended value 53, safe default is 32
+	return a2dp;
+}
+
+void a2dp_free(snd_pcm_a2dp_t * a2dp)
+{
+	DBG("");
+	if (a2dp->sk > 0)
+		close(a2dp->sk);
+	if (a2dp->control_sk > 0)
+		close(a2dp->control_sk);
 
-        free(a2dp);
+	sbc_finish(&a2dp->sbc);
+
+	free(a2dp);
 }
 
 static void sighand(int signo)
 {
-        return;
+	return;
 }
 
 void a2dp_init(void)
 {
-        // set up thread signal handler
-        memset(&actions, 0, sizeof(actions));
-        sigemptyset(&actions.sa_mask);
-        actions.sa_flags = 0;
-        actions.sa_handler = sighand;
-        sigaction(SIGALRM,&actions,NULL);
-        
-        // Start sdp advertising
-        /*
-        g_sdpSessionP = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
-        g_recordP = a2dp_advertise_sdp(g_sdpSessionP);
-        */
+	// set up thread signal handler
+	memset(&actions, 0, sizeof(actions));
+	sigemptyset(&actions.sa_mask);
+	actions.sa_flags = 0;
+	actions.sa_handler = sighand;
+	sigaction(SIGALRM, &actions, NULL);
+
+	// Start sdp advertising
+	/*
+	   g_sdpSessionP = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
+	   g_recordP = a2dp_advertise_sdp(g_sdpSessionP);
+	 */
 }
 
 void a2dp_exit(void)
 {
 }
 
-LPA2DP a2dp_new(char* addr, int framerate)
+LPA2DP a2dp_new(char *addr, int framerate)
 {
-        snd_pcm_a2dp_t *a2dp = NULL;
-        bdaddr_t src, dst;
-        int err; //, pos = -1, use_rfcomm = 0;
-
-        DBG("%s, %d", addr, framerate);
-
-        bacpy(&src, BDADDR_ANY);
-        bacpy(&dst, BDADDR_ANY);
-        str2ba(addr, &dst);
-
-        a2dp = a2dp_alloc();
-        if (!a2dp) {
-                DBG("Can't allocate");
-                return NULL;
-        }
-        if(a2dp) a2dp->sbc.rate=framerate;
+	snd_pcm_a2dp_t *a2dp = NULL;
+	bdaddr_t src, dst;
+	int err;		//, pos = -1, use_rfcomm = 0;
 
-        bacpy(&a2dp->src, &src);
-        bacpy(&a2dp->dst, &dst);
-        //a2dp->use_rfcomm = use_rfcomm;
-
-        err = a2dp_connect(a2dp);
-        if (err < 0) {
-                DBG("Can't connect");
-                goto error;
-        }
+	DBG("%s, %d", addr, framerate);
 
-        return a2dp;
+	bacpy(&src, BDADDR_ANY);
+	bacpy(&dst, BDADDR_ANY);
+	str2ba(addr, &dst);
 
-error:
-        a2dp_free(a2dp);
-        return NULL;
-}
+	a2dp = a2dp_alloc();
+	if (!a2dp) {
+		DBG("Can't allocate");
+		return NULL;
+	}
+	if (a2dp)
+		a2dp->sbc.rate = framerate;
 
-void a2dp_destroy(LPA2DP a2dp)
-{
-        struct stream_cmd close_stream;
-        struct close_stream_rsp close_resp;
+	bacpy(&a2dp->src, &src);
+	bacpy(&a2dp->dst, &dst);
+	//a2dp->use_rfcomm = use_rfcomm;
+
+	err = a2dp_connect(a2dp);
+	if (err < 0) {
+		DBG("Can't connect");
+		goto error;
+	}
 
-        DBG("Begin");
-        a2dp->stop_writing = 1;
-        pthread_kill(a2dp->hListenThread, SIGALRM);
-        pthread_join(a2dp->hListenThread, NULL);
-
-        memset(&close_stream, 0, sizeof(close_stream));
-        memset(&close_resp, 0, sizeof(close_resp));
-
-        // the stream-close used to make the iTech headset lock up and require it to be powercycled
-        // should be tested again now that we drain the queue properly
-
-        init_request(&close_stream.header, AVDTP_CLOSE);
-        close_stream.acp_seid = a2dp->seid;
-        // Use control_sk if it is needed
-        if((a2dp->control_sk>0 && (write(a2dp->control_sk, &close_stream, sizeof(close_stream)) != sizeof(close_stream)))
-        // Else use sk
-        || (write(a2dp->sk, &close_stream, sizeof(close_stream)) != sizeof(close_stream))
-          )
-        {
-                DBG("Couldn't send close_stream (errno=%d:%s)", errno, strerror(errno));
-        }
+	return a2dp;
 
-        a2dp_free(a2dp);
-        DBG("a2dp_destroy(%p) OK", a2dp);
+      error:
+	a2dp_free(a2dp);
+	return NULL;
 }
 
-int a2dp_make_listen_socket(unsigned short psm)
+void a2dp_destroy(LPA2DP a2dp)
 {
-        char* lpszError = NULL;
-        int sockfd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
-        
-        if (sockfd >= 0)
-        {
-                struct sockaddr_l2 addr;
-                memset(&addr, 0, sizeof(addr));
-                addr.l2_family = AF_BLUETOOTH;
-                bacpy(&addr.l2_bdaddr, BDADDR_ANY);
-                addr.l2_psm=htobs(psm);
-                if (bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) >= 0)
-                {
-                        /*
-                        struct l2cap_options opts;
-                        unsigned int iOptSize = sizeof(opts);
-                        // Get default options
-                        if (getsockopt(sockfd, SOL_L2CAP, L2CAP_OPTIONS, &opts, &opt) >= 0)
-                        {
-                                if (setsockopt(sockfd, SOL_L2CAP, L2CAP_OPTIONS, &opts, opt) >= 0)
-                                {
-                        */
-                                        if(listen(sockfd,5)>=0)
-                                        {
-                                        }
-                                        else
-                                        {
-                                                lpszError = "Can't listen.";
-                                        }
-                        /*
-                                }
-                                else
-                                {
-                                        lpszError = "Can't get default L2CAP options.";
-                                }
-                        }
-                        else
-                        {
-                                lpszError = "Can't set L2CAP options.";
-                        }
-                        */
-                }
-                else
-                {
-                        lpszError = "Can't bind socket (already used?).";
-                }
-        }
-        else
-        {
-                lpszError = "Can't create socket.";
-        }
+	struct stream_cmd close_stream;
+	struct close_stream_rsp close_resp;
 
-        if(lpszError)
-        {
-                DBG("%s %s(%d)", lpszError, strerror(errno), errno);
-                close(sockfd);
-                sockfd=-1;
-        }
-        
-        return sockfd;
+	DBG("Begin");
+	a2dp->stop_writing = 1;
+	pthread_kill(a2dp->hListenThread, SIGALRM);
+	pthread_join(a2dp->hListenThread, NULL);
+
+	memset(&close_stream, 0, sizeof(close_stream));
+	memset(&close_resp, 0, sizeof(close_resp));
+
+	// the stream-close used to make the iTech headset lock up and require it to be powercycled
+	// should be tested again now that we drain the queue properly
+
+	init_request(&close_stream.header, AVDTP_CLOSE);
+	close_stream.acp_seid = a2dp->seid;
+	// Use control_sk if it is needed
+	if ((a2dp->control_sk > 0 && (write(a2dp->control_sk, &close_stream, sizeof(close_stream)) != sizeof(close_stream)))
+	    // Else use sk
+	    || (write(a2dp->sk, &close_stream, sizeof(close_stream)) != sizeof(close_stream))
+	    ) {
+		DBG("Couldn't send close_stream (errno=%d:%s)", errno, strerror(errno));
+	}
+
+	a2dp_free(a2dp);
+	DBG("a2dp_destroy(%p) OK", a2dp);
 }
 
-int a2dp_wait_connection( int sockfd, char* szRemote, int iRemoteSize, uint16_t *mtu)
+int a2dp_make_listen_socket(unsigned short psm)
 {
-        // Wait client connection
-        struct sockaddr_l2 addr;
-        socklen_t addrlen = sizeof(addr);
-
-        // Timeouts each second to read variables
-        struct timeval t = { 1, 0 };
-        setsockopt( sockfd, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t));
-        setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
+	char *lpszError = NULL;
+	int sockfd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
 
-        int new_fd = accept(sockfd, (struct sockaddr *) &addr, &addrlen);
+	if (sockfd >= 0) {
+		struct sockaddr_l2 addr;
+		memset(&addr, 0, sizeof(addr));
+		addr.l2_family = AF_BLUETOOTH;
+		bacpy(&addr.l2_bdaddr, BDADDR_ANY);
+		addr.l2_psm = htobs(psm);
+		if (bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) >= 0) {
+			/*
+			   struct l2cap_options opts;
+			   unsigned int iOptSize = sizeof(opts);
+			   // Get default options
+			   if (getsockopt(sockfd, SOL_L2CAP, L2CAP_OPTIONS, &opts, &opt) >= 0)
+			   {
+			   if (setsockopt(sockfd, SOL_L2CAP, L2CAP_OPTIONS, &opts, opt) >= 0)
+			   {
+			 */
+			if (listen(sockfd, 5) >= 0) {
+			} else {
+				lpszError = "Can't listen.";
+			}
+			/*
+			   }
+			   else
+			   {
+			   lpszError = "Can't get default L2CAP options.";
+			   }
+			   }
+			   else
+			   {
+			   lpszError = "Can't set L2CAP options.";
+			   }
+			 */
+		} else {
+			lpszError = "Can't bind socket (already used?).";
+		}
+	} else {
+		lpszError = "Can't create socket.";
+	}
 
-        if (szRemote) *szRemote='\0';
+	if (lpszError) {
+		DBG("%s %s(%d)", lpszError, strerror(errno), errno);
+		close(sockfd);
+		sockfd = -1;
+	}
 
-        if(new_fd >= 0)
-        {
-                // Get default options
-                struct l2cap_options opts;
-                unsigned int iOptSize = sizeof(opts);
-                if (getsockopt(sockfd, SOL_L2CAP, L2CAP_OPTIONS, &opts, &iOptSize) >= 0)
-                {
-                        if (mtu && opts.imtu)
-                                *mtu = opts.imtu;
-                        if (mtu && opts.omtu)
-                                *mtu = opts.omtu;
-                        if (!(*mtu))
-                                *mtu=A2DPMAXIMUMTRANSFERUNITSIZE;
-                }
-                //DBG("Connected [imtu %d, omtu %d, flush_to %d]", opts.imtu, opts.omtu, opts.flush_to);
+	return sockfd;
+}
 
-                if (szRemote) 
-                {
-                        strncpy(szRemote, batostr(&addr.l2_bdaddr), iRemoteSize);
-                        szRemote[iRemoteSize-1] = '\0';
-                }
-        }
-        return new_fd;
+int a2dp_wait_connection(int sockfd, char *szRemote, int iRemoteSize, uint16_t * mtu)
+{
+	// Wait client connection
+	struct sockaddr_l2 addr;
+	socklen_t addrlen = sizeof(addr);
+
+	// Timeouts each second to read variables
+	struct timeval t = { 1, 0 };
+	setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t));
+	setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
+
+	int new_fd = accept(sockfd, (struct sockaddr *) &addr, &addrlen);
+
+	if (szRemote)
+		*szRemote = '\0';
+
+	if (new_fd >= 0) {
+		// Get default options
+		struct l2cap_options opts;
+		unsigned int iOptSize = sizeof(opts);
+		if (getsockopt(sockfd, SOL_L2CAP, L2CAP_OPTIONS, &opts, &iOptSize) >= 0) {
+			if (mtu && opts.imtu)
+				*mtu = opts.imtu;
+			if (mtu && opts.omtu)
+				*mtu = opts.omtu;
+			if (!(*mtu))
+				*mtu = A2DPMAXIMUMTRANSFERUNITSIZE;
+		}
+		//DBG("Connected [imtu %d, omtu %d, flush_to %d]", opts.imtu, opts.omtu, opts.flush_to);
+
+		if (szRemote) {
+			strncpy(szRemote, batostr(&addr.l2_bdaddr), iRemoteSize);
+			szRemote[iRemoteSize - 1] = '\0';
+		}
+	}
+	return new_fd;
 }
 
 // This function handle the bluetooth connection
-int a2dp_handle_avdtp_message(LPA2DP a2dp, int sockfd, struct avdtp_header* sent_packet, struct avdtp_header* answer, int answer_size)
+int a2dp_handle_avdtp_message(LPA2DP a2dp, int sockfd, struct avdtp_header *sent_packet, struct avdtp_header *answer, int answer_size)
 {
-        int result = 0;
-        int wrresult = 0;
-
-        char lpFrame [A2DPMAXIMUMTRANSFERUNITSIZE];
-        int iReceived = recv(sockfd, lpFrame, sizeof(lpFrame), 0);
-        struct avdtp_header* pkt_hdr = (struct avdtp_header*)lpFrame;
-        if(iReceived>0)
-        {
-                // Manage the packet
-                if(sent_packet==NULL)
-                {
-                        int i;
-                        printf("socket %d: Received %d bytes\n", sockfd, iReceived);
-                        for(i = 0; i<iReceived; i++)
-                        {
-                                char c=lpFrame[i];
-                                if(i%16==0) printf("%05d: ", i);
-                                printf("%02x ", c);
-                                if(i%16==15) printf("\n");
-                        }
-                        printf("\n");
-                        result=0;
-                }
-                else if((pkt_hdr->message_type == MESSAGE_TYPE_ACCEPT)                               &&(pkt_hdr->signal_id == sent_packet->signal_id)
-                )
-                {
-                        // Got expected answer
-                        memcpy(answer, lpFrame, answer_size>iReceived?answer_size:iReceived);
-                        result=iReceived;
-                }
-                else
-                {
-                        // Got bad answer
-                        result=0;
-                }
-
-                // Reply to the packet by rejecting it
-                if(pkt_hdr->message_type == MESSAGE_TYPE_COMMAND)
-                {
-                        int accepted = 0;
-                        if(a2dp && pkt_hdr->signal_id == AVDTP_SUSPEND)
-                        {
-                                DBG("Received signal AVDTP_SUSPEND(%d) from set", pkt_hdr->signal_id);
-                                a2dp->pause_writing = 1;
-                                accepted=1;
-                        }
-                        else if(a2dp && pkt_hdr->signal_id == AVDTP_START)
-                        {
-                                DBG("Received signal AVDTP_START(%d) from set", pkt_hdr->signal_id);
-                                a2dp->pause_writing = 0;
-                                accepted=1;
-                        }
-                        else
-                        {
-                                DBG("Unexpected headset directive %d", pkt_hdr->signal_id);
-                        }
-
-                        DBG("Answering command packet (msgtype=%s,signal=%d)", accepted?"MESSAGE_TYPE_ACCEPT":"MESSAGE_TYPE_REJECT", pkt_hdr->signal_id);
-                        // Reject a command received
-                        pkt_hdr->message_type = accepted?MESSAGE_TYPE_ACCEPT:MESSAGE_TYPE_REJECT;
+	int result = 0;
+	int wrresult = 0;
 
-                        wrresult = write(sockfd, pkt_hdr, sizeof(*pkt_hdr));
+	char lpFrame[A2DPMAXIMUMTRANSFERUNITSIZE];
+	int iReceived = recv(sockfd, lpFrame, sizeof(lpFrame), 0);
+	struct avdtp_header *pkt_hdr = (struct avdtp_header *) lpFrame;
+	if (iReceived > 0) {
+		// Manage the packet
+		if (sent_packet == NULL) {
+			int i;
+			printf("socket %d: Received %d bytes\n", sockfd, iReceived);
+			for (i = 0; i < iReceived; i++) {
+				char c = lpFrame[i];
+				if (i % 16 == 0)
+					printf("%05d: ", i);
+				printf("%02x ", c);
+				if (i % 16 == 15)
+					printf("\n");
+			}
+			printf("\n");
+			result = 0;
+		} else if ((pkt_hdr->message_type == MESSAGE_TYPE_ACCEPT) && (pkt_hdr->signal_id == sent_packet->signal_id)
+		    ) {
+			// Got expected answer
+			memcpy(answer, lpFrame, answer_size > iReceived ? answer_size : iReceived);
+			result = iReceived;
+		} else {
+			// Got bad answer
+			result = 0;
+		}
+
+		// Reply to the packet by rejecting it
+		if (pkt_hdr->message_type == MESSAGE_TYPE_COMMAND) {
+			int accepted = 0;
+			if (a2dp && pkt_hdr->signal_id == AVDTP_SUSPEND) {
+				DBG("Received signal AVDTP_SUSPEND(%d) from set", pkt_hdr->signal_id);
+				a2dp->pause_writing = 1;
+				accepted = 1;
+			} else if (a2dp && pkt_hdr->signal_id == AVDTP_START) {
+				DBG("Received signal AVDTP_START(%d) from set", pkt_hdr->signal_id);
+				a2dp->pause_writing = 0;
+				accepted = 1;
+			} else {
+				DBG("Unexpected headset directive %d", pkt_hdr->signal_id);
+			}
 
-                        if(wrresult != sizeof(*pkt_hdr))
-                        {
-                                DBG("FAILED Answering command packet (msgtype=%s,signal=%d) wrresult=%d/%d (errno=%d:%s)", accepted?"MESSAGE_TYPE_ACCEPT":"MESSAGE_TYPE_REJECT", pkt_hdr->signal_id, wrresult, sizeof(*pkt_hdr), errno, strerror(errno));
-                        }
-                }
-                else
-                {
-                        DBG("Read non command packet (msgtype=%d,signal=%d)", pkt_hdr->message_type, pkt_hdr->signal_id);
-                }
-        }
-        else
-        {
-                result=iReceived;
-                if(errno!=EAGAIN)
-                        printf("socket %d: Receive failed %d (errno=%d:%s)\n", sockfd, iReceived, errno, strerror(errno));
-        }
+			DBG("Answering command packet (msgtype=%s,signal=%d)", accepted ? "MESSAGE_TYPE_ACCEPT" : "MESSAGE_TYPE_REJECT", pkt_hdr->signal_id);
+			// Reject a command received
+			pkt_hdr->message_type = accepted ? MESSAGE_TYPE_ACCEPT : MESSAGE_TYPE_REJECT;
+
+			wrresult = write(sockfd, pkt_hdr, sizeof(*pkt_hdr));
+
+			if (wrresult != sizeof(*pkt_hdr)) {
+				DBG("FAILED Answering command packet (msgtype=%s,signal=%d) wrresult=%d/%d (errno=%d:%s)", accepted ? "MESSAGE_TYPE_ACCEPT" : "MESSAGE_TYPE_REJECT", pkt_hdr->signal_id,
+				    wrresult, sizeof(*pkt_hdr), errno, strerror(errno));
+			}
+		} else {
+			DBG("Read non command packet (msgtype=%d,signal=%d)", pkt_hdr->message_type, pkt_hdr->signal_id);
+		}
+	} else {
+		result = iReceived;
+		if (errno != EAGAIN)
+			printf("socket %d: Receive failed %d (errno=%d:%s)\n", sockfd, iReceived, errno, strerror(errno));
+	}
 
-        return result;
+	return result;
 }
-
Index: alsa-plugins/alsalib.c
===================================================================
RCS file: alsa-plugins/alsalib.c
diff -N alsa-plugins/alsalib.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ alsa-plugins/alsalib.c	31 Aug 2006 15:58:57 -0000
@@ -0,0 +1,203 @@
+/*
+*
+*  BlueZ - Bluetooth protocol stack for Linux
+*
+*  Copyright (C) 2004-2005  Marcel Holtmann <marcel@holtmann.org>
+*
+*
+*  This library is free software; you can redistribute it and/or
+*  modify it under the terms of the GNU Lesser General Public
+*  License as published by the Free Software Foundation; either
+*  version 2.1 of the License, or (at your option) any later version.
+*
+*  This library 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
+*  Lesser General Public License for more details.
+*
+*  You should have received a copy of the GNU Lesser General Public
+*  License along with this library; if not, write to the Free Software
+*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <malloc.h>
+#include <signal.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/select.h>
+
+#include <netinet/in.h>
+
+#include <pthread.h>
+#include <alsa/asoundlib.h>
+#include "alsalib.h"
+#include "a2dpd_protocol.h"
+
+#define NBSDPRETRIESMAX 0
+#define NONSPECAUDIO 1
+#define BUFS 2048
+
+#define DBG(fmt, arg...) { if(errno!=0) printf("DEBUG: %s: (errno=%d:%s)" fmt "\n" , __FUNCTION__ , errno, strerror(errno), ## arg); else printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg); errno=0; }
+
+//#define DBG(fmt, arg...)  printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg)
+//#define DBG(D...)
+
+static struct sigaction actions;
+
+typedef struct snd_pcm_alsa {
+	snd_pcm_t *playback_handle;
+} snd_pcm_alsa_t;
+
+/*
+*   Underrun and suspend recovery
+*/
+
+static int xrun_recovery(snd_pcm_t * handle, int err)
+{
+	if (err == -EPIPE) {	/* under-run */
+		err = snd_pcm_prepare(handle);
+		if (err < 0)
+			printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
+		return 0;
+	} else if (err == -ESTRPIPE) {
+		while ((err = snd_pcm_resume(handle)) == -EAGAIN)
+			sleep(1);	/* wait until the suspend flag is released */
+		if (err < 0) {
+			err = snd_pcm_prepare(handle);
+			if (err < 0)
+				printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
+		}
+		return 0;
+	}
+	return err;
+}
+
+int alsa_transfer_raw(LPALSA alsa, const char *pcm_buffer, int pcm_buffer_size)
+{
+	int result = 0;
+
+	result = snd_pcm_writei(alsa->playback_handle, pcm_buffer, pcm_buffer_size / A2DPD_FRAME_BYTES);
+	switch (result) {
+	case -EBADFD:
+		DBG("EBADFD(%d)", result);
+		break;
+	case -EPIPE:
+		// To manage underrun, we will try to ignore
+		xrun_recovery(alsa->playback_handle, result);
+		//result = 0;
+		DBG("EPIPE(%d)", result);
+		break;
+	case -ESTRPIPE:
+		xrun_recovery(alsa->playback_handle, result);
+		//result=0;
+		DBG("ESTRPIPE(%d)", result);
+		break;
+	}
+
+	return result;
+}
+
+snd_pcm_alsa_t *alsa_alloc(void)
+{
+	snd_pcm_alsa_t *alsa;
+	alsa = malloc(sizeof(*alsa));
+	if (!alsa)
+		return NULL;
+
+	memset(alsa, 0, sizeof(*alsa));
+	return alsa;
+}
+
+void alsa_free(snd_pcm_alsa_t * alsa)
+{
+	free(alsa);
+}
+
+static void sighand(int signo)
+{
+	return;
+}
+
+void alsa_init(void)
+{
+	// set up thread signal handler
+	memset(&actions, 0, sizeof(actions));
+	sigemptyset(&actions.sa_mask);
+	actions.sa_flags = 0;
+	actions.sa_handler = sighand;
+	sigaction(SIGALRM, &actions, NULL);
+}
+
+void alsa_exit(void)
+{
+}
+
+LPALSA alsa_new(char *device, int framerate)
+{
+	DBG("");
+	snd_pcm_alsa_t *alsa = NULL;
+	snd_pcm_hw_params_t *hw_params = NULL;
+	int bcontinue = 1;
+	char *devname = (device && device[0]) ? device : "plughw:0,0";
+
+	alsa = alsa_alloc();
+	if (!alsa) {
+		DBG("Can't allocate");
+		return NULL;
+	}
+	// Setup alsa
+	bcontinue = bcontinue && (snd_pcm_open(&alsa->playback_handle, devname, SND_PCM_STREAM_PLAYBACK, 0) >= 0);
+	DBG("snd_pcm_open()==%d", bcontinue);
+	bcontinue = bcontinue && (snd_pcm_hw_params_malloc(&hw_params) >= 0);
+	DBG("snd_pcm_hw_params_malloc()==%d", bcontinue);
+	bcontinue = bcontinue && (snd_pcm_hw_params_any(alsa->playback_handle, hw_params) >= 0);
+	DBG("snd_pcm_hw_params_any()==%d", bcontinue);
+	bcontinue = bcontinue && (snd_pcm_hw_params_set_access(alsa->playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) >= 0);
+	DBG("snd_pcm_hw_params_set_access()==%d", bcontinue);
+	bcontinue = bcontinue && (snd_pcm_hw_params_set_format(alsa->playback_handle, hw_params, SND_PCM_FORMAT_S16_LE) >= 0);
+	DBG("snd_pcm_hw_params_set_format()==%d", bcontinue);
+	bcontinue = bcontinue && (snd_pcm_hw_params_set_rate(alsa->playback_handle, hw_params, framerate, 0) >= 0);
+	DBG("snd_pcm_hw_params_set_rate()==%d", bcontinue);
+	bcontinue = bcontinue && (snd_pcm_hw_params_set_channels(alsa->playback_handle, hw_params, 2) >= 0);
+	DBG("snd_pcm_hw_params_set_channels()==%d", bcontinue);
+	bcontinue = bcontinue && (snd_pcm_hw_params(alsa->playback_handle, hw_params) >= 0);
+	DBG("snd_pcm_hw_params()==%d", bcontinue);
+	bcontinue = bcontinue && (snd_pcm_prepare(alsa->playback_handle) >= 0);
+	DBG("snd_pcm_prepare()==%d", bcontinue);
+
+	// Free if allocated
+	if (hw_params)
+		snd_pcm_hw_params_free(hw_params);
+
+	if (alsa->playback_handle != NULL) {
+	}
+
+	if (!bcontinue) {
+		alsa_destroy(alsa);
+		alsa = NULL;
+	}
+
+	return alsa;
+}
+
+void alsa_destroy(LPALSA alsa)
+{
+	DBG("");
+	if (alsa->playback_handle != NULL) {
+		snd_pcm_close(alsa->playback_handle);
+	}
+	alsa_free(alsa);
+	DBG("OK");
+}
Index: alsa-plugins/alsalib.h
===================================================================
RCS file: alsa-plugins/alsalib.h
diff -N alsa-plugins/alsalib.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ alsa-plugins/alsalib.h	31 Aug 2006 15:58:57 -0000
@@ -0,0 +1,48 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2004-2005  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __ALSA_LIB_H__
+#define __ALSA_LIB_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#define A2DPMAXIMUMTRANSFERUNITSIZE 610
+
+typedef struct snd_pcm_alsa* LPALSA;
+
+// Global library initialisation
+extern void alsa_init( void);
+extern void alsa_exit( void);
+
+// Connect to alsa
+extern LPALSA alsa_new( char* device, int framerate);
+extern void alsa_destroy( LPALSA a2dp);
+
+// transfers data
+extern int alsa_transfer_raw( LPALSA a2dp, const char* pcm_buffer, int pcm_buffer_size);
+
+#endif
Index: alsa-plugins/pcm_a2dpd.c
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/alsa-plugins/pcm_a2dpd.c,v
retrieving revision 1.4
diff -u -r1.4 pcm_a2dpd.c
--- alsa-plugins/pcm_a2dpd.c	17 Aug 2006 14:06:27 -0000	1.4
+++ alsa-plugins/pcm_a2dpd.c	31 Aug 2006 15:58:57 -0000
@@ -51,381 +51,358 @@
 #define DBG(fmt, arg...)  printf("DEBUG: %s: (errno=%d:%s)" fmt "\n" , __FUNCTION__ , errno, strerror(errno), ## arg)
 //#define DBG(D...)
 
-static char     g_srcfilename           [512];
+static char g_srcfilename[512];
 
 // Signal handler, there is a strange SIGPIPE when the daemon is not running
 // We catch it to not quit
 void sighand(int signo)
 {
-        printf("A2DPD CTL in signal handler %d\n", signo);
-        return;
+	printf("A2DPD CTL in signal handler %d\n", signo);
+	return;
 }
 
-typedef struct snd_pcm_a2dp
-{
-        snd_pcm_ioplug_t io;
-        int sk;
-        int rate;
-        int channels;
-        snd_pcm_sframes_t num;
-        unsigned int frame_bytes;
-        TIMERINFO TimerInfos;
+typedef struct snd_pcm_a2dp {
+	snd_pcm_ioplug_t io;
+	int sk;
+	int rate;
+	int channels;
+	snd_pcm_sframes_t num;
+	unsigned int frame_bytes;
+	TIMERINFO TimerInfos;
 } snd_pcm_a2dp_t;
 
-static int a2dp_disconnect(snd_pcm_a2dp_t *a2dp)
+static int a2dp_disconnect(snd_pcm_a2dp_t * a2dp)
 {
-        close_socket(a2dp->sk);
-        a2dp->sk = -1;
-        return 0;
-}
-
-static int a2dp_connect(snd_pcm_a2dp_t *a2dp)
-{
-        if(a2dp->sk <= 0)
-        {
-                int sockfd = make_client_socket();
-                a2dp->sk = -1;
-                if(sockfd>0)
-                {
-                        int32_t client_type = A2DPD_PLUGIN_PCM_WRITE;
-                        if(send_socket(sockfd, &client_type, sizeof(client_type))==sizeof(client_type))
-                        {
-                                a2dp->sk = sockfd;
-                                syslog(LOG_INFO, "Connected a2dp %p, sk %d", a2dp, a2dp->sk);
-                        }
-                        else
-                        {
-                                close_socket(sockfd);
-                                syslog(LOG_WARNING, "Connected a2dp %p, sk %d, Authorisation failed", a2dp, a2dp->sk);
-                        }
-                }
-                else
-                {
-                        syslog(LOG_ERR, "Socket failed a2dp %p, sk %d", a2dp, a2dp->sk);
-                }
-        }
-        return 0;
+	close_socket(a2dp->sk);
+	a2dp->sk = -1;
+	return 0;
+}
+
+static int a2dp_connect(snd_pcm_a2dp_t * a2dp)
+{
+	if (a2dp->sk <= 0) {
+		int sockfd = make_client_socket();
+		a2dp->sk = -1;
+		if (sockfd > 0) {
+			int32_t client_type = A2DPD_PLUGIN_PCM_WRITE;
+			if (send_socket(sockfd, &client_type, sizeof(client_type)) == sizeof(client_type)) {
+				a2dp->sk = sockfd;
+				syslog(LOG_INFO, "Connected a2dp %p, sk %d", a2dp, a2dp->sk);
+			} else {
+				close_socket(sockfd);
+				syslog(LOG_WARNING, "Connected a2dp %p, sk %d, Authorisation failed", a2dp, a2dp->sk);
+			}
+		} else {
+			syslog(LOG_ERR, "Socket failed a2dp %p, sk %d", a2dp, a2dp->sk);
+		}
+	}
+	return 0;
 }
 
 static inline snd_pcm_a2dp_t *a2dp_alloc(void)
 {
-        snd_pcm_a2dp_t *a2dp;
-        DBG("Init");
-        a2dp = malloc(sizeof(*a2dp));
-        if (!a2dp)
-                return NULL;
-        memset(a2dp, 0, sizeof(*a2dp));
-        a2dp->sk = -1;
+	snd_pcm_a2dp_t *a2dp;
+	DBG("Init");
+	a2dp = malloc(sizeof(*a2dp));
+	if (!a2dp)
+		return NULL;
+	memset(a2dp, 0, sizeof(*a2dp));
+	a2dp->sk = -1;
 
-        {
-                get_config_filename(g_srcfilename, sizeof(g_srcfilename));
-                int rate = read_config_int(g_srcfilename, "a2dpd", "rate", A2DPD_FRAME_RATE);
-                a2dp->TimerInfos.fps = (float)((((float)rate)*((float)A2DPD_FRAME_BYTES)/((float)A2DPD_BLOCK_SIZE))/1.0);
-        }
-        DBG("OK");
-        return a2dp;
+	{
+		get_config_filename(g_srcfilename, sizeof(g_srcfilename));
+		int rate = read_config_int(g_srcfilename, "a2dpd", "rate", A2DPD_FRAME_RATE);
+		a2dp->TimerInfos.fps = (float) ((((float) rate) * ((float) A2DPD_FRAME_BYTES) / ((float) A2DPD_BLOCK_SIZE)) / 1.0);
+	}
+	DBG("OK");
+	return a2dp;
 }
 
-static inline void a2dp_free(snd_pcm_a2dp_t *a2dp)
+static inline void a2dp_free(snd_pcm_a2dp_t * a2dp)
 {
-        DBG("Finishing");
-        a2dp_disconnect(a2dp);
-        free(a2dp);
-        DBG("OK");
+	DBG("Finishing");
+	a2dp_disconnect(a2dp);
+	free(a2dp);
+	DBG("OK");
 }
 
-static int a2dp_start(snd_pcm_ioplug_t *io)
+static int a2dp_start(snd_pcm_ioplug_t * io)
 {
-        //snd_pcm_a2dp_t *a2dp = io->private_data;
-        //FIXME
-        return 0;
+	//snd_pcm_a2dp_t *a2dp = io->private_data;
+	//FIXME
+	return 0;
 }
 
-static int a2dp_stop(snd_pcm_ioplug_t *io)
+static int a2dp_stop(snd_pcm_ioplug_t * io)
 {
-        //snd_pcm_a2dp_t *a2dp = io->private_data;
-        return 0;
+	//snd_pcm_a2dp_t *a2dp = io->private_data;
+	return 0;
 }
 
-static snd_pcm_sframes_t a2dp_pointer(snd_pcm_ioplug_t *io)
+static snd_pcm_sframes_t a2dp_pointer(snd_pcm_ioplug_t * io)
 {
-        snd_pcm_a2dp_t *a2dp = io->private_data;
-        return a2dp->num;
+	snd_pcm_a2dp_t *a2dp = io->private_data;
+	return a2dp->num;
 }
 
 // This is the main transfer func which does the transfer and sleep job
-static snd_pcm_sframes_t a2dp_transfer2(snd_pcm_ioplug_t *io,
-                        char* buf,
-                        int32_t datatoread)
-{
-        snd_pcm_a2dp_t* a2dp = io->private_data;
-        int transfer = 0;
-
-        // Connect if needed and send
-        a2dp_connect(a2dp);
-        if(transfer>=0) transfer=send_socket(a2dp->sk, &datatoread, sizeof(datatoread));
-        if(transfer>=0) transfer=send_socket(a2dp->sk, buf, datatoread);
-
-        // Disconnect if error detected
-        if(transfer<0) a2dp_disconnect(a2dp);
-
-        // The data are sent to the daemon that act as a proxy thus we double transfer delay to compensate latency
-        a2dp_timer_notifyframe(&a2dp->TimerInfos);
-        a2dp_timer_sleep(&a2dp->TimerInfos, 4*A2DPTIMERPREDELAY); 
-
-        // Stats
-        if(a2dp->TimerInfos.display>0)
-        {
-                if(errno != 0 || transfer <= 0)
-                {
-                        syslog( LOG_INFO, "send_socket(%d bytes)=%d (errno=%d:%s)", datatoread, transfer, errno, strerror(errno));
-                }
-        }
+static snd_pcm_sframes_t a2dp_transfer2(snd_pcm_ioplug_t * io, char *buf, int32_t datatoread)
+{
+	snd_pcm_a2dp_t *a2dp = io->private_data;
+	int transfer = 0;
 
-        // update pointer, tell alsa we're done
-        a2dp->num += datatoread / a2dp->frame_bytes;
+	// Connect if needed and send
+	a2dp_connect(a2dp);
+	if (transfer >= 0)
+		transfer = send_socket(a2dp->sk, &datatoread, sizeof(datatoread));
+	if (transfer >= 0)
+		transfer = send_socket(a2dp->sk, buf, datatoread);
+
+	// Disconnect if error detected
+	if (transfer < 0)
+		a2dp_disconnect(a2dp);
+
+	// The data are sent to the daemon that act as a proxy thus we double transfer delay to compensate latency
+	a2dp_timer_notifyframe(&a2dp->TimerInfos);
+	a2dp_timer_sleep(&a2dp->TimerInfos, 4 * A2DPTIMERPREDELAY);
+
+	// Stats
+	if (a2dp->TimerInfos.display > 0) {
+		if (errno != 0 || transfer <= 0) {
+			syslog(LOG_INFO, "send_socket(%d bytes)=%d (errno=%d:%s)", datatoread, transfer, errno, strerror(errno));
+		}
+	}
+	// update pointer, tell alsa we're done
+	a2dp->num += datatoread / a2dp->frame_bytes;
 
-        return datatoread / a2dp->frame_bytes;
+	return datatoread / a2dp->frame_bytes;
 }
 
 // also works but sleeps between transfers
 // This is the main transfer func which does the transfer and sleep job
-static snd_pcm_sframes_t a2dp_transfer_all(snd_pcm_ioplug_t *io,
-                        const snd_pcm_channel_area_t *areas,
-                        snd_pcm_uframes_t offset, snd_pcm_uframes_t size)
+static snd_pcm_sframes_t a2dp_transfer_all(snd_pcm_ioplug_t * io, const snd_pcm_channel_area_t * areas, snd_pcm_uframes_t offset, snd_pcm_uframes_t size)
 {
-        snd_pcm_a2dp_t* a2dp = io->private_data;
-        int i = 0;
-        snd_pcm_sframes_t totaltransfered = 0;
-        while(i++<1 && totaltransfered < size)
-        {
-                char* buf = (char *) areas->addr + (areas->first + areas->step * offset) / 8;
-                int datatoread=min(A2DPD_BLOCK_SIZE,size*a2dp->frame_bytes);
-                snd_pcm_sframes_t transfered = a2dp_transfer2(io, buf, datatoread);
-                if(transfered>0)
-                {
-                        offset += transfered;
-                        totaltransfered += transfered;
-                }
-                else
-                {
-                        break;
-                }
-        }
-        return totaltransfered;
+	snd_pcm_a2dp_t *a2dp = io->private_data;
+	int i = 0;
+	snd_pcm_sframes_t totaltransfered = 0;
+	while (i++ < 1 && totaltransfered < size) {
+		char *buf = (char *) areas->addr + (areas->first + areas->step * offset) / 8;
+		int datatoread = min(A2DPD_BLOCK_SIZE, size * a2dp->frame_bytes);
+		snd_pcm_sframes_t transfered = a2dp_transfer2(io, buf, datatoread);
+		if (transfered > 0) {
+			offset += transfered;
+			totaltransfered += transfered;
+		} else {
+			break;
+		}
+	}
+	return totaltransfered;
 }
 
-static int a2dp_close(snd_pcm_ioplug_t *io)
+static int a2dp_close(snd_pcm_ioplug_t * io)
 {
-        snd_pcm_a2dp_t *a2dp = io->private_data;
-        a2dp_disconnect(a2dp);
-        a2dp_free(a2dp);
-        return 0;
+	snd_pcm_a2dp_t *a2dp = io->private_data;
+	a2dp_disconnect(a2dp);
+	a2dp_free(a2dp);
+	return 0;
 }
 
-static int a2dp_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params)
+static int a2dp_params(snd_pcm_ioplug_t * io, snd_pcm_hw_params_t * params)
 {
-        snd_pcm_a2dp_t *a2dp = io->private_data;
-        unsigned int period_bytes;
+	snd_pcm_a2dp_t *a2dp = io->private_data;
+	unsigned int period_bytes;
 
-        DBG("a2dp %p", a2dp);
+	DBG("a2dp %p", a2dp);
 
-        a2dp->frame_bytes = (snd_pcm_format_physical_width(io->format) * io->channels) / 8;
+	a2dp->frame_bytes = (snd_pcm_format_physical_width(io->format) * io->channels) / 8;
 
-        period_bytes = io->period_size * a2dp->frame_bytes;
+	period_bytes = io->period_size * a2dp->frame_bytes;
 
-        DBG("format %s rate %d channels %d", snd_pcm_format_name(io->format),
-                                        io->rate, io->channels);
+	DBG("format %s rate %d channels %d", snd_pcm_format_name(io->format), io->rate, io->channels);
 
-        DBG("frame_bytes %d period_bytes %d period_size %ld buffer_size %ld",
-                a2dp->frame_bytes, period_bytes, io->period_size, io->buffer_size);
+	DBG("frame_bytes %d period_bytes %d period_size %ld buffer_size %ld", a2dp->frame_bytes, period_bytes, io->period_size, io->buffer_size);
 
-        return 0;
+	return 0;
 }
 
-static int a2dp_prepare(snd_pcm_ioplug_t *io)
+static int a2dp_prepare(snd_pcm_ioplug_t * io)
 {
-        snd_pcm_a2dp_t *a2dp = io->private_data;
-        DBG("a2dp %p", a2dp);
-        a2dp->num = 0;
-        a2dp->rate = io->rate;
-        a2dp->channels = io->channels;
-        return 0;
+	snd_pcm_a2dp_t *a2dp = io->private_data;
+	DBG("a2dp %p", a2dp);
+	a2dp->num = 0;
+	a2dp->rate = io->rate;
+	a2dp->channels = io->channels;
+	return 0;
 }
 
-static int a2dp_drain(snd_pcm_ioplug_t *io)
+static int a2dp_drain(snd_pcm_ioplug_t * io)
 {
-        snd_pcm_a2dp_t *a2dp = io->private_data;
-        DBG("a2dp %p", a2dp);
-        return 0;
+	snd_pcm_a2dp_t *a2dp = io->private_data;
+	DBG("a2dp %p", a2dp);
+	return 0;
 }
 
-static int a2dp_descriptors_count(snd_pcm_ioplug_t *io)
+static int a2dp_descriptors_count(snd_pcm_ioplug_t * io)
 {
-        return 1;
+	return 1;
 }
 
-static int a2dp_descriptors(snd_pcm_ioplug_t *io, struct pollfd *pfds, unsigned int space)
+static int a2dp_descriptors(snd_pcm_ioplug_t * io, struct pollfd *pfds, unsigned int space)
 {
-        if (space < 1)
-        {
-                DBG("Can't fill in descriptors");
-                SNDERR("Can't fill in descriptors");
-                return 0;
-        }
-
-        // Alsa does make sure writing now will not block
-        // So give him an always writable socket!
-        pfds[0].fd = fileno(stdout);
-        pfds[0].events = POLLOUT;
-        return 1;
+	if (space < 1) {
+		DBG("Can't fill in descriptors");
+		SNDERR("Can't fill in descriptors");
+		return 0;
+	}
+	// Alsa does make sure writing now will not block
+	// So give him an always writable socket!
+	pfds[0].fd = fileno(stdout);
+	pfds[0].events = POLLOUT;
+	return 1;
 }
 
-static int a2dp_poll(snd_pcm_ioplug_t *io, struct pollfd *pfds,
-                        unsigned int nfds, unsigned short *revents)
+static int a2dp_poll(snd_pcm_ioplug_t * io, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
 {
-        snd_pcm_a2dp_t *a2dp = io->private_data;
-        *revents = pfds[0].revents;
+	snd_pcm_a2dp_t *a2dp = io->private_data;
+	*revents = pfds[0].revents;
 
-        if (a2dp->sk<=0)
-                return 0;
+	if (a2dp->sk <= 0)
+		return 0;
 
-        if (pfds[0].revents & POLLHUP) {
-                a2dp_disconnect(a2dp);
-                snd_pcm_ioplug_reinit_status(&a2dp->io);
-        }
+	if (pfds[0].revents & POLLHUP) {
+		a2dp_disconnect(a2dp);
+		snd_pcm_ioplug_reinit_status(&a2dp->io);
+	}
 
-        return 0;
+	return 0;
 }
 
 static snd_pcm_ioplug_callback_t a2dp_callback = {
-        .close			= a2dp_close,
-        .start			= a2dp_start,
-        .stop			= a2dp_stop,
-        .prepare		= a2dp_prepare,
-        .transfer		= a2dp_transfer_all,
-        .pointer		= a2dp_pointer,
-        .hw_params		= a2dp_params,
-        .drain			= a2dp_drain,
-        .poll_descriptors_count	= a2dp_descriptors_count,
-        .poll_descriptors	= a2dp_descriptors,
-        .poll_revents		= a2dp_poll,
+	.close = a2dp_close,
+	.start = a2dp_start,
+	.stop = a2dp_stop,
+	.prepare = a2dp_prepare,
+	.transfer = a2dp_transfer_all,
+	.pointer = a2dp_pointer,
+	.hw_params = a2dp_params,
+	.drain = a2dp_drain,
+	.poll_descriptors_count = a2dp_descriptors_count,
+	.poll_descriptors = a2dp_descriptors,
+	.poll_revents = a2dp_poll,
 };
 
 // Force alsa to give use the 44100 hz sound
 // Or say alsa we will accept only 44100hz?
-static int a2dp_constraint(snd_pcm_a2dp_t *a2dp)
+static int a2dp_constraint(snd_pcm_a2dp_t * a2dp)
 {
-        snd_pcm_ioplug_t *io = &a2dp->io;
-        snd_pcm_access_t access_list[] = {
-                SND_PCM_ACCESS_RW_INTERLEAVED,
-                SND_PCM_ACCESS_MMAP_INTERLEAVED,
-        };
-        unsigned int format[2], channel[2], rate[2];
-        int err;
+	snd_pcm_ioplug_t *io = &a2dp->io;
+	snd_pcm_access_t access_list[] = {
+		SND_PCM_ACCESS_RW_INTERLEAVED,
+		SND_PCM_ACCESS_MMAP_INTERLEAVED,
+	};
+	unsigned int format[2], channel[2], rate[2];
+	int err;
 
-        syslog(LOG_INFO, "[build %s %s] a2dp %p", __DATE__, __TIME__, a2dp);
+	syslog(LOG_INFO, "[build %s %s] a2dp %p", __DATE__, __TIME__, a2dp);
 
-        err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 2, access_list);
-        if (err < 0)
-                return err;
+	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 2, access_list);
+	if (err < 0)
+		return err;
 
-        format[0] = SND_PCM_FORMAT_S16_LE;
+	format[0] = SND_PCM_FORMAT_S16_LE;
 
-        err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 1, format);
-        if (err < 0)
-                return err;
+	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 1, format);
+	if (err < 0)
+		return err;
 
-        channel[0] = 1;
-        channel[1] = 2;
+	channel[0] = 1;
+	channel[1] = 2;
 
-        err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_CHANNELS, 2, channel);
-        if (err < 0)
-                return err;
+	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_CHANNELS, 2, channel);
+	if (err < 0)
+		return err;
 
-        get_config_filename(g_srcfilename, sizeof(g_srcfilename));
-        rate[0] = read_config_int(g_srcfilename, "a2dpd", "rate", A2DPD_FRAME_RATE);
-        //rate[1] = 48000;
+	get_config_filename(g_srcfilename, sizeof(g_srcfilename));
+	rate[0] = read_config_int(g_srcfilename, "a2dpd", "rate", A2DPD_FRAME_RATE);
+	//rate[1] = 48000;
 
-        err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE, 1, rate);
-        if (err < 0)
-                return err;
+	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE, 1, rate);
+	if (err < 0)
+		return err;
 
-        err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 8192, 8192);
-        if (err < 0)
-                return err;
+	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 8192, 8192);
+	if (err < 0)
+		return err;
 
-        err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 2, 2);
-        if (err < 0)
-                return err;
+	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 2, 2);
+	if (err < 0)
+		return err;
 
-        return 0;
+	return 0;
 }
 
 SND_PCM_PLUGIN_DEFINE_FUNC(a2dpd)
 {
-        snd_pcm_a2dp_t *a2dp = NULL;
-        snd_config_iterator_t i, next;
-        int err = 0;
-
-        DBG("name %s mode %d", name, mode);
-
-        // set up thread signal handler
-        signal(SIGPIPE,sighand);
-
-        snd_config_for_each(i, next, conf) {
-                snd_config_t *n = snd_config_iterator_entry(i);
-                const char *id;
-
-                if (snd_config_get_id(n, &id) < 0)
-                        continue;
-
-                if (!strcmp(id, "comment") || !strcmp(id, "type"))
-                        continue;
-
-                // Ignore old options
-                if (strstr("ipaddr bdaddr port src dst use_rfcomm", id))
-                        continue;
-
-                SNDERR("Unknown field %s", id);
-                return -EINVAL;
-        }
-
-        a2dp = a2dp_alloc();
-        if (!a2dp)
-        {
-                SNDERR("Can't allocate plugin data");
-                return -ENOMEM;
-        }
-
-        // Connect
-        a2dp_connect(a2dp);
-
-        // Notify plugin
-        a2dp->io.version      = SND_PCM_IOPLUG_VERSION;
-        a2dp->io.name         = "Bluetooth Advanced Audio Distribution";
-        a2dp->io.mmap_rw      = 0;
-        a2dp->io.callback     = &a2dp_callback;
-        a2dp->io.private_data = a2dp;
-
-        err = snd_pcm_ioplug_create(&a2dp->io, name, stream, mode);
-        if (err < 0)
-                goto error;
-
-        err = a2dp_constraint(a2dp);
-        if (err < 0) {
-                snd_pcm_ioplug_delete(&a2dp->io);
-                goto error;
-        }
-
-        *pcmp = a2dp->io.pcm;
-        return 0;
-
-error:
-        a2dp_disconnect(a2dp);
-        a2dp_free(a2dp);
+	snd_pcm_a2dp_t *a2dp = NULL;
+	snd_config_iterator_t i, next;
+	int err = 0;
+
+	DBG("name %s mode %d", name, mode);
+
+	// set up thread signal handler
+	signal(SIGPIPE, sighand);
+
+	snd_config_for_each(i, next, conf) {
+		snd_config_t *n = snd_config_iterator_entry(i);
+		const char *id;
+
+		if (snd_config_get_id(n, &id) < 0)
+			continue;
+
+		if (!strcmp(id, "comment") || !strcmp(id, "type"))
+			continue;
+
+		// Ignore old options
+		if (strstr("ipaddr bdaddr port src dst use_rfcomm", id))
+			continue;
+
+		SNDERR("Unknown field %s", id);
+		return -EINVAL;
+	}
+
+	a2dp = a2dp_alloc();
+	if (!a2dp) {
+		SNDERR("Can't allocate plugin data");
+		return -ENOMEM;
+	}
+	// Connect
+	a2dp_connect(a2dp);
+
+	// Notify plugin
+	a2dp->io.version = SND_PCM_IOPLUG_VERSION;
+	a2dp->io.name = "Bluetooth Advanced Audio Distribution";
+	a2dp->io.mmap_rw = 0;
+	a2dp->io.callback = &a2dp_callback;
+	a2dp->io.private_data = a2dp;
+
+	err = snd_pcm_ioplug_create(&a2dp->io, name, stream, mode);
+	if (err < 0)
+		goto error;
+
+	err = a2dp_constraint(a2dp);
+	if (err < 0) {
+		snd_pcm_ioplug_delete(&a2dp->io);
+		goto error;
+	}
+
+	*pcmp = a2dp->io.pcm;
+	return 0;
+
+      error:
+	a2dp_disconnect(a2dp);
+	a2dp_free(a2dp);
 
-        return err;
+	return err;
 }
 
 SND_PCM_PLUGIN_SYMBOL(a2dpd);
Index: alsa-plugins/sample.a2dprc
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/alsa-plugins/sample.a2dprc,v
retrieving revision 1.2
diff -u -r1.2 sample.a2dprc
--- alsa-plugins/sample.a2dprc	17 Aug 2006 14:06:27 -0000	1.2
+++ alsa-plugins/sample.a2dprc	31 Aug 2006 15:58:57 -0000
@@ -1,10 +1,38 @@
 [a2dpd]
+#
+# Rate
+# use 32000 if your headset seems to not support 44100 (HP works well at 44100, Sonorix at 32000)
+# Alsa output may not work depending on your graphics card
+# Very few players supports it (xmms does, but not amarok/gxine engine)
+#
 rate=44100
 #rate=32000
-address=00:0D:44:2A:17:C7
+enablereversestereo=0
+
+#
+# AVRCP Commands to run
+#
 cmdplay=xmms --play
 cmdpause=xmms --pause
 cmdprev=xmms --rew
 cmdnext=xmms --fwd
 cmdnew=xmms --play
+# Put to 0 to ignore AVRCP (if your computer freezes when commands are received)
+enableavrcp=1
+
+#
+# Audio routing
+#
+# If set to 1 (at a2dp startup only) a2dp will reread configuration file
+# for audio routing changes each second
+enablerereadconfig=1
+
+# 0 => Bluetooth A2DP Sink
+# 1 => Alsa
+enableredirectalsa=0
+
+# Your bluetooth headset address
+address=00:08:F4:30:07:64
 
+# Address of your alsa output (default : plughw:0,0) you have to know what to do
+alsaoutput=

[-- Attachment #3: Type: text/plain, Size: 373 bytes --]

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

[-- Attachment #4: Type: text/plain, Size: 164 bytes --]

_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

  reply	other threads:[~2006-08-31 16:04 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-08-23 16:55 [Bluez-devel] Small patch to a2dpd Frédéric DALLEAU
2006-08-23 17:53 ` Brad Midgley
2006-08-24  8:44   ` Frédéric DALLEAU
2006-08-30 14:45 ` Brad Midgley
2006-08-31 16:04   ` Frédéric DALLEAU [this message]
2006-09-01 12:57     ` [Bluez-devel] Big " andy
2006-09-01 18:25       ` Michael Frey
2006-09-02 16:05     ` Brad Midgley
2006-09-02 20:06       ` [Bluez-devel] RE : " Frederic Dalleau
2006-09-06  3:58         ` Brad Midgley
2006-09-06  8:52           ` Frédéric DALLEAU
2006-09-07 23:00             ` Brad Midgley
2006-09-02 16:08     ` [Bluez-devel] " Brad Midgley
2006-09-02 17:01       ` Brad Midgley
  -- strict thread matches above, loose matches on Subject: below --
2006-09-02  6:04 Li, Lea
2006-09-02 13:02 ` Michael Frey
2006-09-02  6:21 Li, Lea
2006-09-06  3:06 ` Brad Midgley
2006-09-06  3:12 Li, Lea
2006-09-06  3:38 ` Brad Midgley
2006-09-06  9:33   ` Frédéric DALLEAU
2006-09-07 16:48     ` Andrew Waldram
2006-09-07 19:47       ` Brad Midgley
2006-09-07 20:36         ` Michael Frey
2006-09-07 22:46           ` Brad Midgley
2006-09-07 21:06         ` Andrew Waldram
2006-09-07 22:52           ` Brad Midgley

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=44F7088F.6090606@palmsource.com \
    --to=frederic.dalleau@palmsource.com \
    --cc=bluez-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox