comparison libao2/ao_jack.c @ 13889:adb9a0d74ca0

Improved A-V sync, patch by Ed Wildgoose [lists(at)wildgooses<dot>com].
author reimar
date Sun, 07 Nov 2004 11:03:50 +0000
parents 2d188ebe0f3b
children a92101a7eb49
comparison
equal deleted inserted replaced
13888:a28322ddafba 13889:adb9a0d74ca0
8 * It uses bio2jack (http://bio2jack.sf.net/). 8 * It uses bio2jack (http://bio2jack.sf.net/).
9 * 9 *
10 */ 10 */
11 11
12 #include <stdio.h> 12 #include <stdio.h>
13 #include <jack/jack.h>
13 14
14 #include "audio_out.h" 15 #include "audio_out.h"
15 #include "audio_out_internal.h" 16 #include "audio_out_internal.h"
16 #include "afmt.h" 17 #include "afmt.h"
17 #include "../config.h" 18 #include "../config.h"
18 #include "../mp_msg.h" 19 #include "../mp_msg.h"
19 20
20 //#include "bio2jack.h" 21 //#include "bio2jack.h"
21 22
22 static int driver = 0; 23 static int driver = 0;
24 long latency = 0;
25 long approx_bytes_in_jackd = 0;
23 26
24 //bio2jack stuff: 27 //bio2jack stuff:
25 #define ERR_SUCCESS 0 28 #define ERR_SUCCESS 0
26 #define ERR_OPENING_JACK 1 29 #define ERR_OPENING_JACK 1
27 #define ERR_RATE_MISMATCH 2 30 #define ERR_RATE_MISMATCH 2
32 int JACK_Close(int deviceID); /* return 0 for success */ 35 int JACK_Close(int deviceID); /* return 0 for success */
33 void JACK_Reset(int deviceID); /* free all buffered data and reset several values in the device */ 36 void JACK_Reset(int deviceID); /* free all buffered data and reset several values in the device */
34 long JACK_Write(int deviceID, char *data, unsigned long bytes); /* returns the number of bytes written */ 37 long JACK_Write(int deviceID, char *data, unsigned long bytes); /* returns the number of bytes written */
35 long JACK_GetJackLatency(int deviceID); /* return the latency in milliseconds of jack */ 38 long JACK_GetJackLatency(int deviceID); /* return the latency in milliseconds of jack */
36 int JACK_SetState(int deviceID, enum status_enum state); /* playing, paused, stopped */ 39 int JACK_SetState(int deviceID, enum status_enum state); /* playing, paused, stopped */
40 int JACK_SetAllVolume(int deviceID, unsigned int volume);
37 int JACK_SetVolumeForChannel(int deviceID, unsigned int channel, unsigned int volume); 41 int JACK_SetVolumeForChannel(int deviceID, unsigned int channel, unsigned int volume);
38 void JACK_GetVolumeForChannel(int deviceID, unsigned int channel, unsigned int *volume); 42 void JACK_GetVolumeForChannel(int deviceID, unsigned int channel, unsigned int *volume);
39 // 43 //
40 44
41 45
69 case AOCONTROL_SET_VOLUME: 73 case AOCONTROL_SET_VOLUME:
70 { 74 {
71 ao_control_vol_t *vol = (ao_control_vol_t *)arg; 75 ao_control_vol_t *vol = (ao_control_vol_t *)arg;
72 unsigned int l = (int )vol->left, 76 unsigned int l = (int )vol->left,
73 r = (int )vol->right, 77 r = (int )vol->right,
78 avg_vol = (l + r) / 2,
74 err = 0; 79 err = 0;
75 80
76 if((err = JACK_SetVolumeForChannel(driver, 0, l))) { 81 switch (ao_data.channels) {
82 case 6:
83 if((err = JACK_SetVolumeForChannel(driver, 5, avg_vol))) {
77 mp_msg(MSGT_AO, MSGL_ERR, 84 mp_msg(MSGT_AO, MSGL_ERR,
78 "AO: [Jack] Setting left volume failed, error %d\n",err); 85 "AO: [Jack] Setting lfe volume failed, error %d\n",err);
86 return CONTROL_ERROR;
87 }
88 case 5:
89 if((err = JACK_SetVolumeForChannel(driver, 4, avg_vol))) {
90 mp_msg(MSGT_AO, MSGL_ERR,
91 "AO: [Jack] Setting center volume failed, error %d\n",err);
92 return CONTROL_ERROR;
93 }
94 case 4:
95 if((err = JACK_SetVolumeForChannel(driver, 3, r))) {
96 mp_msg(MSGT_AO, MSGL_ERR,
97 "AO: [Jack] Setting rear right volume failed, error %d\n",err);
79 return CONTROL_ERROR; 98 return CONTROL_ERROR;
80 } 99 }
100 case 3:
101 if((err = JACK_SetVolumeForChannel(driver, 2, l))) {
102 mp_msg(MSGT_AO, MSGL_ERR,
103 "AO: [Jack] Setting rear left volume failed, error %d\n",err);
104 return CONTROL_ERROR;
105 }
106 case 2:
81 if((err = JACK_SetVolumeForChannel(driver, 1, r))) { 107 if((err = JACK_SetVolumeForChannel(driver, 1, r))) {
82 mp_msg(MSGT_AO, MSGL_ERR, 108 mp_msg(MSGT_AO, MSGL_ERR,
83 "AO: [Jack] Setting right volume failed, error %d\n",err); 109 "AO: [Jack] Setting right volume failed, error %d\n",err);
84 return CONTROL_ERROR; 110 return CONTROL_ERROR;
85 } 111 }
112 case 1:
113 if((err = JACK_SetVolumeForChannel(driver, 0, l))) {
114 mp_msg(MSGT_AO, MSGL_ERR,
115 "AO: [Jack] Setting left volume failed, error %d\n",err);
116 return CONTROL_ERROR;
117 }
118 }
86 119
87 return CONTROL_OK; 120 return CONTROL_OK;
88 } 121 }
89 } 122 }
90 123
96 { 129 {
97 int err, m, frag_spec; 130 int err, m, frag_spec;
98 unsigned long rate; 131 unsigned long rate;
99 unsigned int bits_per_sample; 132 unsigned int bits_per_sample;
100 133
134 unsigned long jack_port_flags=JackPortIsPhysical;
135 unsigned int jack_port_name_count=0;
136 const char *jack_port_name=NULL;
137
101 mp_msg(MSGT_AO, MSGL_INFO, "AO: [Jack] Initialising library.\n"); 138 mp_msg(MSGT_AO, MSGL_INFO, "AO: [Jack] Initialising library.\n");
102 JACK_Init(); 139 JACK_Init();
140
141 if (ao_subdevice) {
142 jack_port_flags = 0;
143 jack_port_name_count = 1;
144 jack_port_name = ao_subdevice;
145 mp_msg(MSGT_AO, MSGL_INFO, "AO: [Jack] Trying to use jack device:%s.\n", ao_subdevice);
146 }
103 147
104 switch (format) { 148 switch (format) {
105 case AFMT_U8: 149 case AFMT_U8:
106 case AFMT_S8: 150 case AFMT_S8:
107 format = AFMT_U8; 151 format = AFMT_U8;
115 break; 159 break;
116 } 160 }
117 161
118 rate = rate_hz; 162 rate = rate_hz;
119 163
120 err = JACK_Open(&driver, bits_per_sample, &rate, channels); 164 err = JACK_OpenEx(&driver, bits_per_sample, &rate, channels, channels,
165 &jack_port_name, jack_port_name_count, jack_port_flags);
121 166
122 /* if sample rates doesn't match try to open device with jack's rate and 167 /* if sample rates doesn't match try to open device with jack's rate and
123 * let mplayer convert it (rate now contains that which jackd use) */ 168 * let mplayer convert it (rate now contains that which jackd use) */
124 if(err == ERR_RATE_MISMATCH) { 169 if(err == ERR_RATE_MISMATCH) {
125 mp_msg(MSGT_AO, MSGL_INFO, 170 mp_msg(MSGT_AO, MSGL_INFO,
126 "AO: [Jack] Sample rate mismatch, trying to resample.\n"); 171 "AO: [Jack] Sample rate mismatch, trying to resample.\n");
127 172
128 err = JACK_Open(&driver, bits_per_sample, &rate, channels); 173 err = JACK_OpenEx(&driver, bits_per_sample, &rate, channels, channels,
174 &jack_port_name, jack_port_name_count, jack_port_flags);
129 } 175 }
130 176
131 /* any other error */ 177 /* any other error */
132 if(err != ERR_SUCCESS) { 178 if(err != ERR_SUCCESS) {
133 mp_msg(MSGT_AO, MSGL_ERR, 179 mp_msg(MSGT_AO, MSGL_ERR,
134 "AO: [Jack] JACK_Open() failed, error %d\n", err); 180 "AO: [Jack] JACK_Open() failed, error %d\n", err);
135 return 0; 181 return 0;
136 } 182 }
137 183
184 err = JACK_SetAllVolume(driver, 100);
185 if(err != ERR_SUCCESS) {
186 // This is not fatal, but would be peculiar...
187 mp_msg(MSGT_AO, MSGL_ERR,
188 "AO: [Jack] JACK_SetAllVolume() failed, error %d\n", err);
189 }
190
191 latency = JACK_GetJackLatency(driver);
192
138 ao_data.format = format; 193 ao_data.format = format;
139 ao_data.channels = channels; 194 ao_data.channels = channels;
140 ao_data.samplerate = rate; 195 ao_data.samplerate = rate;
141 ao_data.bps = ( rate * channels * m ); 196 ao_data.bps = ( rate * channels * m );
142 197
198 // Rather rough way to find out the rough number of bytes buffered
199 approx_bytes_in_jackd = JACK_GetJackBufferedBytes(driver) * 2;
200
143 mp_msg(MSGT_AO, MSGL_INFO, 201 mp_msg(MSGT_AO, MSGL_INFO,
144 "AO: [Jack] OK. I'm ready to go (%d Hz/%d channels/%d bit)\n", 202 "AO: [Jack] OK. I'm ready to go (%d Hz/%d channels/%d bit)\n",
145 ao_data.samplerate, ao_data.channels, bits_per_sample); 203 ao_data.samplerate, ao_data.channels, bits_per_sample);
146 204
147 return 1; 205 return 1;
150 208
151 static void uninit(int immed) 209 static void uninit(int immed)
152 { 210 {
153 int errval = 0; 211 int errval = 0;
154 212
155 JACK_Reset(driver);
156
157 if((errval = JACK_Close(driver))) 213 if((errval = JACK_Close(driver)))
158 mp_msg(MSGT_AO, MSGL_ERR, 214 mp_msg(MSGT_AO, MSGL_ERR,
159 "AO: [Jack] error closing device, error %d\n", errval); 215 "AO: [Jack] error closing device, error %d\n", errval);
160 } 216 }
161 217
179 235
180 236
181 static void reset() 237 static void reset()
182 { 238 {
183 JACK_Reset(driver); 239 JACK_Reset(driver);
240 latency = JACK_GetJackLatency(driver);
241 // Rather rough way to find out the rough number of bytes buffered
242 approx_bytes_in_jackd = JACK_GetJackBufferedBytes(driver) * 2;
184 } 243 }
185 244
186 245
187 static int get_space() 246 static int get_space()
188 { 247 {
190 } 249 }
191 250
192 251
193 static float get_delay() 252 static float get_delay()
194 { 253 {
195 return (float )JACK_GetJackLatency(driver); 254 float ret = 0;
196 } 255 ret = (JACK_GetBytesStored(driver) + approx_bytes_in_jackd + latency) / (float)ao_data.bps;
197 256 return ret;
257 }
258