@@ -580,17 +580,34 @@ static int bluealsa_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params)
580
580
debug2 ("Changing BlueALSA PCM configuration: %u ch, %u Hz -> %u ch, %u Hz" ,
581
581
pcm -> ba_pcm .channels , pcm -> ba_pcm .sampling , channels , sampling );
582
582
583
- if (ba_dbus_pcm_select_codec (& pcm -> dbus_ctx , pcm -> ba_pcm .pcm_path ,
584
- pcm -> ba_pcm .codec .name , pcm -> ba_pcm_codec_config , pcm -> ba_pcm_codec_config_len ,
583
+ const char * codec_name = pcm -> ba_pcm .codec .name ;
584
+ if (!ba_dbus_pcm_select_codec (& pcm -> dbus_ctx , pcm -> ba_pcm .pcm_path ,
585
+ codec_name , pcm -> ba_pcm_codec_config , pcm -> ba_pcm_codec_config_len ,
585
586
channels , sampling , BA_PCM_SELECT_CODEC_FLAG_NONE , & err )) {
586
- pcm -> ba_pcm .channels = channels ;
587
- pcm -> ba_pcm .sampling = sampling ;
588
- }
589
- else {
590
587
SNDERR ("Couldn't change BlueALSA PCM configuration: %s" , err .message );
591
588
return - dbus_error_to_errno (& err );
592
589
}
593
590
591
+ /* After new codec selection, it is necessary to update the PCM data.
592
+ * We will do it the off-line manner (without server interaction) to
593
+ * speed up the process. */
594
+
595
+ pcm -> ba_pcm .channels = channels ;
596
+ pcm -> ba_pcm .sampling = sampling ;
597
+
598
+ for (size_t i = 0 ; i < pcm -> ba_pcm_codecs .codecs_len ; i ++ ) {
599
+ const struct ba_pcm_codec * codec = & pcm -> ba_pcm_codecs .codecs [i ];
600
+ if (strcmp (codec -> name , codec_name ) == 0 ) {
601
+ for (size_t j = 0 ; j < ARRAYSIZE (codec -> channel_maps ); j ++ )
602
+ if (codec -> channels [j ] == channels ) {
603
+ memcpy (pcm -> ba_pcm .channel_map , codec -> channel_maps [j ],
604
+ sizeof (pcm -> ba_pcm .channel_map ));
605
+ break ;
606
+ }
607
+ break ;
608
+ }
609
+ }
610
+
594
611
}
595
612
596
613
#if BLUEALSA_HW_PARAMS_FIX
@@ -1133,6 +1150,76 @@ static int bluealsa_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfd,
1133
1150
return - ENODEV ;
1134
1151
}
1135
1152
1153
+ static enum snd_pcm_chmap_position ba_channel_map_to_position (const char * tag ) {
1154
+
1155
+ static const struct {
1156
+ const char * tag ;
1157
+ enum snd_pcm_chmap_position pos ;
1158
+ } mapping [] = {
1159
+ { "MONO" , SND_CHMAP_MONO },
1160
+ { "FL" , SND_CHMAP_FL },
1161
+ { "FR" , SND_CHMAP_FR },
1162
+ { "RL" , SND_CHMAP_RL },
1163
+ { "RR" , SND_CHMAP_RR },
1164
+ { "FC" , SND_CHMAP_FC },
1165
+ { "LFE" , SND_CHMAP_LFE },
1166
+ { "SL" , SND_CHMAP_SL },
1167
+ { "SR" , SND_CHMAP_SR },
1168
+ };
1169
+
1170
+ for (size_t i = 0 ; i < ARRAYSIZE (mapping ); i ++ )
1171
+ if (strcmp (tag , mapping [i ].tag ) == 0 )
1172
+ return mapping [i ].pos ;
1173
+ return SND_CHMAP_UNKNOWN ;
1174
+ }
1175
+
1176
+ static snd_pcm_chmap_query_t * * bluealsa_query_chmaps (snd_pcm_ioplug_t * io ) {
1177
+ struct bluealsa_pcm * pcm = io -> private_data ;
1178
+
1179
+ const struct ba_pcm_codec * codec = & pcm -> ba_pcm .codec ;
1180
+ for (size_t i = 0 ; i < pcm -> ba_pcm_codecs .codecs_len ; i ++ )
1181
+ if (strcmp (pcm -> ba_pcm_codecs .codecs [i ].name , codec -> name ) == 0 ) {
1182
+ codec = & pcm -> ba_pcm_codecs .codecs [i ];
1183
+ break ;
1184
+ }
1185
+
1186
+ snd_pcm_chmap_query_t * * maps ;
1187
+ if ((maps = malloc (sizeof (* maps ) * (ARRAYSIZE (codec -> channel_maps ) + 1 ))) == NULL )
1188
+ return NULL ;
1189
+
1190
+ maps [ARRAYSIZE (codec -> channel_maps )] = NULL ;
1191
+ for (size_t i = 0 ; i < ARRAYSIZE (codec -> channel_maps ); i ++ ) {
1192
+
1193
+ unsigned int channels ;
1194
+ if ((channels = codec -> channels [i ]) == 0 )
1195
+ break ;
1196
+
1197
+ maps [i ] = malloc (sizeof (* maps [i ]) + (channels * sizeof (* maps [i ]-> map .pos )));
1198
+ maps [i ]-> type = SND_CHMAP_TYPE_FIXED ;
1199
+ maps [i ]-> map .channels = channels ;
1200
+
1201
+ for (size_t j = 0 ; j < channels ; j ++ )
1202
+ maps [i ]-> map .pos [j ] = ba_channel_map_to_position (codec -> channel_maps [i ][j ]);
1203
+
1204
+ }
1205
+
1206
+ return maps ;
1207
+ }
1208
+
1209
+ static snd_pcm_chmap_t * bluealsa_get_chmap (snd_pcm_ioplug_t * io ) {
1210
+ struct bluealsa_pcm * pcm = io -> private_data ;
1211
+
1212
+ snd_pcm_chmap_t * map ;
1213
+ if ((map = malloc (sizeof (* map ) + (io -> channels * sizeof (* map -> pos )))) == NULL )
1214
+ return NULL ;
1215
+
1216
+ map -> channels = io -> channels ;
1217
+ for (size_t i = 0 ; i < io -> channels ; i ++ )
1218
+ map -> pos [i ] = ba_channel_map_to_position (pcm -> ba_pcm .channel_map [i ]);
1219
+
1220
+ return map ;
1221
+ }
1222
+
1136
1223
static const snd_pcm_ioplug_callback_t bluealsa_callback = {
1137
1224
.start = bluealsa_start ,
1138
1225
.stop = bluealsa_stop ,
@@ -1149,6 +1236,8 @@ static const snd_pcm_ioplug_callback_t bluealsa_callback = {
1149
1236
.poll_descriptors_count = bluealsa_poll_descriptors_count ,
1150
1237
.poll_descriptors = bluealsa_poll_descriptors ,
1151
1238
.poll_revents = bluealsa_poll_revents ,
1239
+ .query_chmaps = bluealsa_query_chmaps ,
1240
+ .get_chmap = bluealsa_get_chmap ,
1152
1241
};
1153
1242
1154
1243
static int str2bdaddr (const char * str , bdaddr_t * ba ) {
0 commit comments