Mercurial > mplayer.hg
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 |