+static void card_info_free(pa_card_info* i) {
+ if (i->proplist)
+ pa_proplist_free(i->proplist);
+
+ pa_xfree(i->profiles);
+
+ if (i->n_profiles) {
+ uint32_t j;
+
+ for (j = 0; j < i->n_profiles; j++)
+ pa_xfree(i->profiles2[j]);
+
+ pa_xfree(i->profiles2);
+ }
+
+ if (i->ports) {
+ uint32_t j;
+
+ for (j = 0; j < i->n_ports; j++) {
+ if (i->ports[j]) {
+ if (i->ports[j]->profiles)
+ pa_xfree(i->ports[j]->profiles);
+ if (i->ports[j]->profiles2)
+ pa_xfree(i->ports[j]->profiles2);
+ if (i->ports[j]->proplist)
+ pa_proplist_free(i->ports[j]->proplist);
+ }
+ }
+
+ pa_xfree(i->ports[0]);
+ pa_xfree(i->ports);
+ }
+}
+
+static int fill_card_port_info(pa_context *context, pa_tagstruct* t, pa_card_info* i) {
+ uint32_t j, k, l;
+
+ if (pa_tagstruct_getu32(t, &i->n_ports) < 0)
+ return -PA_ERR_PROTOCOL;
+
+ if (i->n_ports == 0) {
+ i->ports = NULL;
+ return 0;
+ }
+
+ i->ports = pa_xnew0(pa_card_port_info*, i->n_ports+1);
+ i->ports[0] = pa_xnew0(pa_card_port_info, i->n_ports);
+
+ for (j = 0; j < i->n_ports; j++) {
+ uint8_t direction;
+ uint32_t available;
+ pa_card_port_info* port = i->ports[j] = &i->ports[0][j];
+
+ port->proplist = pa_proplist_new();
+
+ if (pa_tagstruct_gets(t, &port->name) < 0 ||
+ pa_tagstruct_gets(t, &port->description) < 0 ||
+ pa_tagstruct_getu32(t, &port->priority) < 0 ||
+ pa_tagstruct_getu32(t, &available) < 0 ||
+ pa_tagstruct_getu8(t, &direction) < 0 ||
+ pa_tagstruct_get_proplist(t, port->proplist) < 0 ||
+ pa_tagstruct_getu32(t, &port->n_profiles) < 0) {
+
+ return -PA_ERR_PROTOCOL;
+ }
+
+ if (available > PA_PORT_AVAILABLE_YES ||
+ direction > PA_DIRECTION_OUTPUT + PA_DIRECTION_INPUT) {
+
+ return -PA_ERR_PROTOCOL;
+ }
+
+ port->direction = direction;
+ port->available = available;
+
+ if (port->n_profiles > 0) {
+ port->profiles = pa_xnew0(pa_card_profile_info*, i->n_profiles+1);
+ port->profiles2 = pa_xnew0(pa_card_profile_info2*, i->n_profiles+1);
+
+ for (k = 0; k < port->n_profiles; k++) {
+ const char* profilename;
+
+ if (pa_tagstruct_gets(t, &profilename) < 0)
+ return -PA_ERR_PROTOCOL;
+
+ for (l = 0; l < i->n_profiles; l++) {
+ if (pa_streq(i->profiles[l].name, profilename)) {
+ port->profiles[k] = &i->profiles[l];
+ port->profiles2[k] = i->profiles2[l];
+ break;
+ }
+ }
+
+ if (l >= i->n_profiles)
+ return -PA_ERR_PROTOCOL;
+ }
+ }
+ if (context->version >= 27) {
+ if (pa_tagstruct_gets64(t, &port->latency_offset) < 0)
+ return -PA_ERR_PROTOCOL;
+ } else
+ port->latency_offset = 0;
+ }
+
+ return 0;
+}
+
+static int fill_card_profile_info(pa_context *context, pa_tagstruct* t, pa_card_info* i) {
+ uint32_t j;
+
+ i->profiles = pa_xnew0(pa_card_profile_info, i->n_profiles+1);
+ i->profiles2 = pa_xnew0(pa_card_profile_info2*, i->n_profiles+1);
+
+ for (j = 0; j < i->n_profiles; j++) {
+ if (pa_tagstruct_gets(t, &i->profiles[j].name) < 0 ||
+ pa_tagstruct_gets(t, &i->profiles[j].description) < 0 ||
+ pa_tagstruct_getu32(t, &i->profiles[j].n_sinks) < 0 ||
+ pa_tagstruct_getu32(t, &i->profiles[j].n_sources) < 0 ||
+ pa_tagstruct_getu32(t, &i->profiles[j].priority) < 0)
+ return -PA_ERR_PROTOCOL;
+
+ i->profiles2[j] = pa_xnew0(pa_card_profile_info2, 1);
+ i->profiles2[j]->name = i->profiles[j].name;
+ i->profiles2[j]->description = i->profiles[j].description;
+ i->profiles2[j]->n_sinks = i->profiles[j].n_sinks;
+ i->profiles2[j]->n_sources = i->profiles[j].n_sources;
+ i->profiles2[j]->priority = i->profiles[j].priority;
+ i->profiles2[j]->available = 1;
+
+ if (context->version >= 29) {
+ uint32_t av;
+
+ if (pa_tagstruct_getu32(t, &av) < 0)
+ return -PA_ERR_PROTOCOL;
+
+ i->profiles2[j]->available = av;
+ }
+ }
+
+ return 0;
+}
+