public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
* [Bluez-devel] Small patch to a2dpd
@ 2006-08-23 16:55 Frédéric DALLEAU
  2006-08-23 17:53 ` Brad Midgley
  2006-08-30 14:45 ` Brad Midgley
  0 siblings, 2 replies; 14+ messages in thread
From: Frédéric DALLEAU @ 2006-08-23 16:55 UTC (permalink / raw)
  To: BlueZ development

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

Hi Brad,

Latest patch : Default daemon logfile is /dev/null. Try to open an l2cap 
socket with short timeout before doing  sdp_connect that can last very 
long. Also a script called a2dpair that wrap hcitool and passkey-agent 
as an effort to simplify pairing and a2dpd setup :D
What about Matthew's patches? I plan to move to getopt and cleanup 
indent and traces so having them integrated first would be better as 
there are new options.

Frédéric


[-- Attachment #2: a2dpd.patch --]
[-- Type: text/x-patch, Size: 20722 bytes --]

? .deps
? .libs
? Makefile
? Makefile.in
? a2play
? a2recv
? aclocal.m4
? autom4te.cache
? avrecv
? avsnd
? btsco
? btsco2
? config.guess
? config.h
? config.h.in
? config.log
? config.status
? config.sub
? configure
? depcomp
? install-sh
? libtool
? missing
? stamp-h1
? alsa-plugins/.deps
? alsa-plugins/.libs
? alsa-plugins/Makefile
? alsa-plugins/Makefile.in
? alsa-plugins/a2dp_ipc.lo
? alsa-plugins/a2dp_timer.lo
? alsa-plugins/a2dpd
? alsa-plugins/ctl_a2dpd.lo
? alsa-plugins/ctl_sco.lo
? alsa-plugins/libasound_module_ctl_a2dpd.la
? alsa-plugins/libasound_module_ctl_sco.la
? alsa-plugins/libasound_module_pcm_a2dp.la
? alsa-plugins/libasound_module_pcm_a2dpd.la
? alsa-plugins/libasound_module_pcm_sco.la
? alsa-plugins/pcm_a2dp.lo
? alsa-plugins/pcm_a2dpd.lo
? alsa-plugins/pcm_sco.lo
? avdtp/.deps
? avdtp/.libs
? avdtp/Makefile
? avdtp/Makefile.in
? avdtp/avtest
? sbc/.deps
? sbc/.libs
? sbc/Makefile
? sbc/Makefile.in
? sbc/rcplay
? sbc/sbcdec
? sbc/sbcenc
? sbc/sbcinfo
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	23 Aug 2006 16:43:12 -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 (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.4
diff -u -r1.4 a2dpd.c
--- alsa-plugins/a2dpd.c	17 Aug 2006 14:06:27 -0000	1.4
+++ alsa-plugins/a2dpd.c	23 Aug 2006 16:43:13 -0000
@@ -95,10 +95,10 @@
                 chdir("/");
         }
 
-        // Redirect output to file in silent mode, verbose will print output to stdin/out/err
+        // Redirect output to file (default /dev/null) in silent mode, verbose will print output to stdin/out/err
         if(!bVerbose)
         {
-        int fd;
+                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);
@@ -764,6 +764,7 @@
                                         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);
@@ -771,16 +772,18 @@
                                                 {
                                                         printf("avdtp: socket %d: Received frame, start %s\n", new_fd, g_sCmdNew);
                                                         play=1;
+                                                        count=0;
                                                         break;
                                                 }
-                                                else
+                                                else if(iReceived<0)
                                                 {
-                                                        if(iReceived!=EAGAIN)
+                                                        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));
+                                        while(!bSigINTReceived && (iReceived>=0 || errno==EAGAIN) && count<10);
                                         printf("avdtp: socket %d: timed out\n", new_fd);
                                         close_socket(new_fd);
 
@@ -852,7 +855,6 @@
                                 }
                                 else
                                 {
-
                                         if(errno!=EAGAIN)
                                         {
                                                 printf("a2dp_wait_connection failed (AVRCP socket) : %d (errno=%d:%s)\n", new_fd, errno, strerror(errno));
@@ -970,7 +972,7 @@
         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),  "/tmp/a2dpd.log");
+        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++)
Index: alsa-plugins/a2dplib.c
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/alsa-plugins/a2dplib.c,v
retrieving revision 1.4
diff -u -r1.4 a2dplib.c
--- alsa-plugins/a2dplib.c	17 Aug 2006 14:06:27 -0000	1.4
+++ alsa-plugins/a2dplib.c	23 Aug 2006 16:43:13 -0000
@@ -54,6 +54,7 @@
 #include "sbc.h"
 #include "../a2dp.h"
 
+#define NBSDPRETRIESMAX 0
 #define NONSPECAUDIO 1
 #define BUFS 2048
 // In fact sbc blocks are 76 bytes long, so a group of them is either 608 or 684 bytes
@@ -64,6 +65,7 @@
 #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...)
 
@@ -194,7 +196,6 @@
         struct set_config_resp s_resp;
         struct stream_cmd open_stream;
         struct open_stream_rsp open_resp;
-        DBG("Begin SEID = %d", seid);
 
         memset(&put_req, 0, sizeof(put_req));
         init_request(&put_req.header, AVDTP_GET_CAPABILITIES);
@@ -205,10 +206,7 @@
                 DBG("Couldn't request capabilities for SEID = %d", seid);
                 return (-1);
         }
-        else
-        {
-                DBG("Requested Capabilities for SEID = %d",seid);
-        }
+
         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 ||
@@ -316,10 +314,8 @@
                 return (-1);
         }
 
-        DBG("Sent set configurations command");
-        
         size = read(s, &s_resp, sizeof(s_resp));
-        DBG("Got a Set Configurations (%d bytes) Response (msgtype=%d,pkttype=%d,lbl=%d,sig=%d,rfa=%d)", 
+        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,
@@ -336,20 +332,103 @@
                 return (-1);
         }
 
-        DBG("Sent open stream command");
-
         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);
         }
 
-        DBG("Got open stream confirm");
-
         *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)
+{
+        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;
+        }
+
+        /* 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;
+        }
+
+        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;
+
+        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)
 {
@@ -361,17 +440,28 @@
         int err;
         int tries;
 
-        DBG("Begin");
+	// 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)
+	{
+		close(tmpsk);
+	}
+	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));
-                sleep(1);
-                if(++tries > 2) {
+                if(++tries > NBSDPRETRIESMAX) {
                         break;
-                }
+			}
+                sleep(1);
         }
         if (!sess) {
-                DBG( "Warning: failed to connect to SDP server: %s", strerror(errno));
+                DBG( "Warning: failed to connect to SDP server");
                 if(psm) *psm = 25;
                 if(flags) *flags = 0;
                 return 0;
@@ -448,84 +538,6 @@
         sdp_close(sess);
         return 0;
 }
-// Connecting on PSM 25
-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;
-        
-        DBG("Begin");
-        sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
-        if (sk < 0) {
-                DBG( "Can't create socket. %s(%d)",
-                        strerror(errno), errno);
-                return -1;
-        }
-
-        DBG( "Connecting to bluetooth");
-
-        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;
-        }
-
-        /* 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;
-        }
-
-        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);
-                sleep(1);
-                if(++tries > 2) {
-                        close(sk);
-                        return -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;
-
-        return sk;
-}
 
 int connect_stream(bdaddr_t *src, bdaddr_t *dst, int *cmdfd_return, sbc_t *sbc, int* seid_return, int* omtu)
 {
@@ -543,9 +555,6 @@
         uint16_t mtu = 0;
         int tries, res;
 
-        DBG("Begin");
-        DBG( "Using address: %s", batostr(dst));
-
         if (detect_a2dp(src, dst, &psm_cmd, &flags) < 0) {
                 DBG( "could not find A2DP services on device %s", batostr(dst));
                 return -1;
@@ -831,7 +840,11 @@
 {
         snd_pcm_a2dp_t* a2dp = (snd_pcm_a2dp_t*)param;
 
-        if(a2dp->control_sk<0) return NULL;
+        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);
 
@@ -895,7 +908,6 @@
         int sk = -1;
         int control_sk = -1;
         errno=0;
-        DBG("a2dp %p", a2dp);
         /*
         if(a2dp->use_rfcomm) {
                 sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
@@ -943,20 +955,23 @@
         a2dp->pause_writing = 0;
         a2dp->stop_writing = 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_attr_destroy(&tattr);
-        return 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_attr_destroy(&tattr);
+	}
+
+        return sk;
 }
 
 snd_pcm_a2dp_t *a2dp_alloc(void)
 {
         snd_pcm_a2dp_t *a2dp;
-        DBG("Begin");
         a2dp = malloc(sizeof(*a2dp));
         if (!a2dp)
                 return NULL;
@@ -976,7 +991,7 @@
 
 void a2dp_free(snd_pcm_a2dp_t *a2dp)
 {
-        DBG("Begin");
+        DBG("");
         if (a2dp->sk > 0)
                 close(a2dp->sk);
         if (a2dp->control_sk > 0)
@@ -1018,12 +1033,12 @@
         bdaddr_t src, dst;
         int err; //, pos = -1, use_rfcomm = 0;
 
-        DBG("Begin");
+        DBG("%s, %d", addr, framerate);
+
         bacpy(&src, BDADDR_ANY);
         bacpy(&dst, BDADDR_ANY);
-        DBG("bdaddr/dest is %s", addr);
         str2ba(addr, &dst);
-        
+
         a2dp = a2dp_alloc();
         if (!a2dp) {
                 DBG("Can't allocate");
@@ -1262,7 +1277,7 @@
         {
                 result=iReceived;
                 if(errno!=EAGAIN)
-                        printf("socket %d: Receive failed %d (error %d:%s)\n", sockfd, iReceived, errno, strerror(errno));
+                        printf("socket %d: Receive failed %d (errno=%d:%s)\n", sockfd, iReceived, errno, strerror(errno));
         }
 
         return result;
Index: alsa-plugins/pcm_a2dp.c
===================================================================
RCS file: /cvsroot/bluetooth-alsa/btsco/alsa-plugins/pcm_a2dp.c,v
retrieving revision 1.15
diff -u -r1.15 pcm_a2dp.c
--- alsa-plugins/pcm_a2dp.c	3 Aug 2006 18:02:37 -0000	1.15
+++ alsa-plugins/pcm_a2dp.c	23 Aug 2006 16:43:13 -0000
@@ -818,7 +818,7 @@
 	struct media_packet_header packet_header;
 	struct media_payload_header payload_header;
 	int codesize,datatoread;
-	unsigned long sleeptime;
+	unsigned long sleeptime=0;
 	int written;
 	struct timeval dt;
 	struct timeval timeofday;

[-- 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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Bluez-devel] Small patch to a2dpd
  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
  1 sibling, 1 reply; 14+ messages in thread
From: Brad Midgley @ 2006-08-23 17:53 UTC (permalink / raw)
  To: BlueZ development

Fr=E9d=E9ric

> What about Matthew's patches?

Maybe I missed this. What are his changes?

Brad

-------------------------------------------------------------------------
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 easi=
er
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=3Dlnk&kid=3D120709&bid=3D263057&dat=3D1=
21642
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Bluez-devel] Small patch to a2dpd
  2006-08-23 17:53 ` Brad Midgley
@ 2006-08-24  8:44   ` Frédéric DALLEAU
  0 siblings, 0 replies; 14+ messages in thread
From: Frédéric DALLEAU @ 2006-08-24  8:44 UTC (permalink / raw)
  To: BlueZ development


>> What about Matthew's patches?
>>     =

>
> Maybe I missed this. What are his changes?
>
>   =

see
http://sourceforge.net/mailarchive/forum.php?thread_id=3D30260835&forum_id=
=3D1881
http://sourceforge.net/mailarchive/forum.php?thread_id=3D30262307&forum_id=
=3D1881
Fr=E9d=E9ric



-------------------------------------------------------------------------
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 easi=
er
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=3Dlnk&kid=3D120709&bid=3D263057&dat=3D1=
21642
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Bluez-devel] Small patch to a2dpd
  2006-08-23 16:55 [Bluez-devel] Small patch to a2dpd Frédéric DALLEAU
  2006-08-23 17:53 ` Brad Midgley
@ 2006-08-30 14:45 ` Brad Midgley
  2006-08-31 16:04   ` [Bluez-devel] Big " Frédéric DALLEAU
  1 sibling, 1 reply; 14+ messages in thread
From: Brad Midgley @ 2006-08-30 14:45 UTC (permalink / raw)
  To: BlueZ development

Fr=E9d=E9ric

> Latest patch : Default daemon logfile is /dev/null. Try to open an l2cap
> socket with short timeout before doing  sdp_connect that can last very
> long. Also a script called a2dpair that wrap hcitool and passkey-agent
> as an effort to simplify pairing and a2dpd setup :D
> What about Matthew's patches? I plan to move to getopt and cleanup
> indent and traces so having them integrated first would be better as
> there are new options.

I looked over Matthew's patches and applied them. I applied your "small
patch" which turns out to be bigger than it sounds :)

Brad

-------------------------------------------------------------------------
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 easi=
er
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=3Dlnk&kid=3D120709&bid=3D263057&dat=3D1=
21642
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bluez-devel]  Big patch to a2dpd
  2006-08-30 14:45 ` Brad Midgley
@ 2006-08-31 16:04   ` Frédéric DALLEAU
  2006-09-01 12:57     ` andy
                       ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Frédéric DALLEAU @ 2006-08-31 16:04 UTC (permalink / raw)
  To: BlueZ development

[-- 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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Bluez-devel] Big patch to a2dpd
  2006-08-31 16:04   ` [Bluez-devel] Big " Frédéric DALLEAU
@ 2006-09-01 12:57     ` andy
  2006-09-01 18:25       ` Michael Frey
  2006-09-02 16:05     ` Brad Midgley
  2006-09-02 16:08     ` [Bluez-devel] " Brad Midgley
  2 siblings, 1 reply; 14+ messages in thread
From: andy @ 2006-09-01 12:57 UTC (permalink / raw)
  To: BlueZ development

Hi Fr=E9d=E9ric,

Whoo some patch cant wait to give it a whirl..

On the subject of your DOC nice work very concise

You might like to add
------------------
If you create an ~.asoundrc as follows

pcm.a2dpd {
       type a2dpd
}

Then you can directly add the headphone device (pcm.a2dpd) to any app that
supports alsa plugins correctly, Without affecting the default Gnome/X/KDE
sounds

Known working Apps

Xmms
alsaplayer
VLC (you have to manualy add it to the conf file as the gui wont allow
adding non visible plugins (bug)).

cheers Andy
--------------------------------------
 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=3D 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=E9d=E9ric
>
>



-------------------------------------------------------------------------
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 easi=
er
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=3Dlnk&kid=3D120709&bid=3D263057&dat=3D1=
21642
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Bluez-devel] Big patch to a2dpd
  2006-09-01 12:57     ` andy
@ 2006-09-01 18:25       ` Michael Frey
  0 siblings, 0 replies; 14+ messages in thread
From: Michael Frey @ 2006-09-01 18:25 UTC (permalink / raw)
  To: BlueZ development

Is there a way to have a2dpd use the alsa dmixer?  And does anyone  =

know how to change the default alsa device on the fly.  I know you  =

can change .asoundrc but any running applications need to be  =

restarted in order to pick up the change.  Is there a better way?

Michael

On Sep 1, 2006, at 8:57 AM, andy@samuri.demon.co.uk wrote:

> Hi Fr=E9d=E9ric,
>
> Whoo some patch cant wait to give it a whirl..
>
> On the subject of your DOC nice work very concise
>
> You might like to add
> ------------------
> If you create an ~.asoundrc as follows
>
> pcm.a2dpd {
>        type a2dpd
> }
>
> Then you can directly add the headphone device (pcm.a2dpd) to any  =

> app that
> supports alsa plugins correctly, Without affecting the default  =

> Gnome/X/KDE
> sounds
>
> Known working Apps
>
> Xmms
> alsaplayer
> VLC (you have to manualy add it to the conf file as the gui wont allow
> adding non visible plugins (bug)).
>
> cheers Andy
> --------------------------------------
>  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=3D 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=E9d=E9ric
>>
>>
>
>
>
> ---------------------------------------------------------------------- =

> ---
> 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=3Dlnk&kid=3D120709&bid=3D263057&dat=3D121642
> _______________________________________________
> Bluez-devel mailing list
> Bluez-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/bluez-devel


-------------------------------------------------------------------------
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 easi=
er
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=3Dlnk&kid=3D120709&bid=3D263057&dat=3D1=
21642
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Bluez-devel] Big patch to a2dpd
  2006-08-31 16:04   ` [Bluez-devel] Big " Frédéric DALLEAU
  2006-09-01 12:57     ` andy
@ 2006-09-02 16:05     ` Brad Midgley
  2006-09-02 20:06       ` [Bluez-devel] RE : " Frederic Dalleau
  2006-09-02 16:08     ` [Bluez-devel] " Brad Midgley
  2 siblings, 1 reply; 14+ messages in thread
From: Brad Midgley @ 2006-09-02 16:05 UTC (permalink / raw)
  To: BlueZ development

Fr=E9d=E9ric

thanks for the continued work.

> 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

a few problems:

It only works if the bdaddr is specified in .asoundrc (the old way) as
well as in .a2dprc. Specifying it on the a2dpd command line does not
seem to help.

Audio only came out the left speaker using my itech r35 black set. (My
other sets are up at work)

How do you switch on the fly to wired audio?

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

Could we contribute this stuff to a wiki? I actually have the feeling
that no one of us understands the whole picture. I have an account on
the ubuntu wiki but a better one for our purposes would have no
association with a specific distro...

Brad

-------------------------------------------------------------------------
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 easi=
er
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=3Dlnk&kid=3D120709&bid=3D263057&dat=3D1=
21642
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Bluez-devel] Big patch to a2dpd
  2006-08-31 16:04   ` [Bluez-devel] Big " Frédéric DALLEAU
  2006-09-01 12:57     ` andy
  2006-09-02 16:05     ` Brad Midgley
@ 2006-09-02 16:08     ` Brad Midgley
  2006-09-02 17:01       ` Brad Midgley
  2 siblings, 1 reply; 14+ messages in thread
From: Brad Midgley @ 2006-09-02 16:08 UTC (permalink / raw)
  To: BlueZ development

argh... another problem...

when I just sent that last message via wifi while streaming with xmms,
the audio turned choppy (works for 1s, silence for 1s, repeat) and it
never started working again even after no wifi activity :(

brad

-------------------------------------------------------------------------
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
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Bluez-devel] Big patch to a2dpd
  2006-09-02 16:08     ` [Bluez-devel] " Brad Midgley
@ 2006-09-02 17:01       ` Brad Midgley
  0 siblings, 0 replies; 14+ messages in thread
From: Brad Midgley @ 2006-09-02 17:01 UTC (permalink / raw)
  To: BlueZ development

hey

> argh... another problem...
> 
> when I just sent that last message via wifi while streaming with xmms,
> the audio turned choppy (works for 1s, silence for 1s, repeat) and it
> never started working again even after no wifi activity :(

whoops... not sure if this is better or worse.

what actually happened is my wifi stopped working during the a2dp
streaming. so the computer demand-dialed using my cellphone over
bluetooth and that's when the trouble started. so maybe it would have
recovered once the dun connection was closed.

my r35 is a combo hfp/hsp so it does like to be master and doesn't like
scatternetting. funny if you think about it... the network was a
fully-connected triangle between the three devices when the audio was
breaking up.

brad

-------------------------------------------------------------------------
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
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bluez-devel] RE :  Big patch to a2dpd
  2006-09-02 16:05     ` Brad Midgley
@ 2006-09-02 20:06       ` Frederic Dalleau
  2006-09-06  3:58         ` Brad Midgley
  0 siblings, 1 reply; 14+ messages in thread
From: Frederic Dalleau @ 2006-09-02 20:06 UTC (permalink / raw)
  To: BlueZ development

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

Hi Brad,

> It only works if the bdaddr is specified in .asoundrc (the old way) as
> well as in .a2dprc. Specifying it on the a2dpd command line does not
> seem to help.
Now that you tell it, as the .a2dprc is reread for address changes it will overwrite the value set by command line. You can use, enablerereadconfig=0. The .asoundrc is ignored.

> Audio only came out the left speaker using my itech r35 black set. (My
> other sets are up at work)
I have a reversed stereo. It may be related. I haven't found where but it's one of the main problems. Try enablereversestereo=1 and see if audio comes from the right speaker. This would mean the failure came before compression and transmission.
Also try playing with sound balance on xmms and look at alsamixer -D ctl.a2dpd to see if both internal channel values are the same.
Does the standard a2dp plugin work well with that headset?
I have a faulty headset that does that too. When I shoot it it goes ok :D

> How do you switch on the fly to wired audio?
Modify the .a2dprc file, write enablealsaredirect=1 instead of 0 and save. Yes, file ipc :D

> Could we contribute this stuff to a wiki? 
Man is to my eyes the standard unix doc format. Even gnu info is nothing :D Why not a manpage stored in cvs, there are certainly php scripts that can render a man page in html.

The wiki is good for writing but having some docs in the project is better. The wiki needs to be watched over and there would be no way to automatically provide docs to a distro... The manpage can be installed with unbuntu packages.

[-- Attachment #2: winmail.dat --]
[-- Type: application/ms-tnef, Size: 3586 bytes --]

[-- 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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Bluez-devel] RE :  Big patch to a2dpd
  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
  0 siblings, 1 reply; 14+ messages in thread
From: Brad Midgley @ 2006-09-06  3:58 UTC (permalink / raw)
  To: BlueZ development

Frederic

fyi, I applied the "big patch" to cvs.

>> It only works if the bdaddr is specified in .asoundrc (the old way) as
>> well as in .a2dprc. Specifying it on the a2dpd command line does not
>> seem to help.
> Now that you tell it, as the .a2dprc is reread for address changes it will overwrite the value set by command line. You can use, enablerereadconfig=0. The .asoundrc is ignored.

I think this will lead to unexpected behavior. Normally the command line
 overrides the config file. Maybe we should ignore bdaddr changes in the
config file if the bdaddr was specified on the command line.

Have you looked into using dbus for communicating with the running
a2dpd? I think I read that ALP is going to use dbus for things like this.

>> Audio only came out the left speaker using my itech r35 black set. (My
>> other sets are up at work)
> I have a reversed stereo. It may be related. I haven't found where but it's one of the main problems. Try enablereversestereo=1 and see if audio comes from the right speaker. This would mean the failure came before compression and transmission.
> Also try playing with sound balance on xmms and look at alsamixer -D ctl.a2dpd to see if both internal channel values are the same.
> Does the standard a2dp plugin work well with that headset?
> I have a faulty headset that does that too. When I shoot it it goes ok :D

enablereversestereo=1 fixes audio so it comes out of both speakers. I've
made this the default in sample.a2dprc.

fyi, if interference makes the stream get behind, the rate of the stream
gets a little wacky for a while and the pitch wanders around for a few
seconds before settling down. fwiw, this is on a machine with intel i810
graphics which seems to "behave" better than nvidia with regard to
interrupt masking.

I was ecstatic to have avrcp "just work" when I used xmms to try things out.

fyi, the itech r35 has a combo play/pause button that seems to always
send "play" even when the music is already playing. Maybe we need to
pause if we get a play message during playback.

>> How do you switch on the fly to wired audio?
> Modify the .a2dprc file, write enablealsaredirect=1 instead of 0 and save. Yes, file ipc :D
> 
>> Could we contribute this stuff to a wiki? 
> Man is to my eyes the standard unix doc format. Even gnu info is nothing :D Why not a manpage stored in cvs, there are certainly php scripts that can render a man page in html.
> 
> The wiki is good for writing but having some docs in the project is better. The wiki needs to be watched over and there would be no way to automatically provide docs to a distro... The manpage can be installed with unbuntu packages.

I agree the manpage is essential but I'm going to break with tradition
for now and use the wiki for our in-progress stuff. It also motivates me
to get things down in some form of documentation when I don't have to
worry too much about coordination of other efforts.

I put a placeholder here:
http://wiki.linuxquestions.org/wiki/Bluetoooth-alsa
linuxquestions.org seems like an ok spot for this kind of thing.

I will put wiki snapshots in the project in some form when doing
releases or cvs tags.

Brad

-------------------------------------------------------------------------
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
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Bluez-devel] RE :  Big patch to a2dpd
  2006-09-06  3:58         ` Brad Midgley
@ 2006-09-06  8:52           ` Frédéric DALLEAU
  2006-09-07 23:00             ` Brad Midgley
  0 siblings, 1 reply; 14+ messages in thread
From: Frédéric DALLEAU @ 2006-09-06  8:52 UTC (permalink / raw)
  To: BlueZ development

Hi Brad,

> Have you looked into using dbus for communicating with the running
> a2dpd? I think I read that ALP is going to use dbus for things like this.
>   =

We still need data persistency, so It would need to
1) listen dbus
2) rewrite the file

> enablereversestereo=3D1 fixes audio so it comes out of both speakers. I've
> made this the default in sample.a2dprc.
>   =

It seems that the reverse code is a bit buggy :D which explains why you =

have no sound.
Look at this in a2dpd.c
        } 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] =3D =

(((channel_2&0x0000FFFF)<<16)|(channel_1&0x0000FFFF));
            //pBuffer[j] =3D ( (channel_1 & 0xFFFF0000) | (channel_2 & =

0x0000FFFF) );        // ------------------  remove this line
        }

> fyi, if interference makes the stream get behind, the rate of the stream
> gets a little wacky for a while and the pitch wanders around for a few
> seconds before settling down. fwiw, this is on a machine with intel i810
> graphics which seems to "behave" better than nvidia with regard to
> interrupt masking.
>   =

What do you call interference?


Fr=E9d=E9ric


-------------------------------------------------------------------------
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 easi=
er
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=3Dlnk&kid=3D120709&bid=3D263057&dat=3D1=
21642
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Bluez-devel] RE :  Big patch to a2dpd
  2006-09-06  8:52           ` Frédéric DALLEAU
@ 2006-09-07 23:00             ` Brad Midgley
  0 siblings, 0 replies; 14+ messages in thread
From: Brad Midgley @ 2006-09-07 23:00 UTC (permalink / raw)
  To: BlueZ development

Fr=E9d=E9ric

>> Have you looked into using dbus for communicating with the running
>> a2dpd? I think I read that ALP is going to use dbus for things like this.
>>   =

> We still need data persistency, so It would need to
> 1) listen dbus
> 2) rewrite the file

sure... I do like how dbus integration would also allow us to have
another manager app changing settings.

btw, would it be hard to have wired output by default as long as a2dpd
isn't running?

>> fyi, if interference makes the stream get behind, the rate of the stream
>> gets a little wacky for a while and the pitch wanders around for a few
>> seconds before settling down. fwiw, this is on a machine with intel i810
>> graphics which seems to "behave" better than nvidia with regard to
>> interrupt masking.
>>   =

> What do you call interference?

if you walk too far from the transmitter, you get this. also if there's
a bluetooth device scan or motion from my bluetooth mouse things stop.
not much we can do except try to get back to normal as soon as possible
when this stuff happens.

brad

-------------------------------------------------------------------------
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 easi=
er
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=3Dlnk&kid=3D120709&bid=3D263057&dat=3D1=
21642
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2006-09-07 23:00 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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   ` [Bluez-devel] Big " Frédéric DALLEAU
2006-09-01 12:57     ` 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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox