00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <glib.h>
00023
00024 #include "xmmspriv/xmms_xform.h"
00025 #include "xmms/xmms_log.h"
00026 #include "xmms/xmms_object.h"
00027
00028
00029 struct xmms_stream_type_St {
00030 xmms_object_t obj;
00031 gint priority;
00032 gchar *name;
00033 GList *list;
00034 };
00035
00036 typedef enum xmms_stream_type_val_type_E {
00037 STRING,
00038 INT,
00039 } xmms_stream_type_val_type_t;
00040
00041 typedef struct xmms_stream_type_val_St {
00042 xmms_stream_type_key_t key;
00043 xmms_stream_type_val_type_t type;
00044 union {
00045 char *string;
00046 int num;
00047 } d;
00048 } xmms_stream_type_val_t;
00049
00050
00051 static void
00052 xmms_stream_type_destroy (xmms_object_t *obj)
00053 {
00054 xmms_stream_type_t *st = (xmms_stream_type_t *)obj;
00055 GList *n;
00056
00057 g_free (st->name);
00058
00059 for (n = st->list; n; n = g_list_next (n)) {
00060 xmms_stream_type_val_t *val = n->data;
00061 if (val->type == STRING) {
00062 g_free (val->d.string);
00063 }
00064 g_free (val);
00065 }
00066
00067 g_list_free (st->list);
00068 }
00069
00070 xmms_stream_type_t *
00071 xmms_stream_type_parse (va_list ap)
00072 {
00073 xmms_stream_type_t *res;
00074
00075 res = xmms_object_new (xmms_stream_type_t, xmms_stream_type_destroy);
00076 if (!res) {
00077 return NULL;
00078 }
00079
00080 res->priority = -1;
00081 res->name = NULL;
00082
00083 for (;;) {
00084 xmms_stream_type_val_t *val;
00085 xmms_stream_type_key_t key;
00086
00087 key = va_arg (ap, int);
00088 if (key == XMMS_STREAM_TYPE_END)
00089 break;
00090
00091 if (key == XMMS_STREAM_TYPE_NAME) {
00092 res->name = g_strdup (va_arg (ap, char *));
00093 continue;
00094 }
00095
00096 if (key == XMMS_STREAM_TYPE_PRIORITY) {
00097 res->priority = va_arg (ap, int);
00098 continue;
00099 }
00100
00101 val = g_new0 (xmms_stream_type_val_t, 1);
00102 val->key = key;
00103
00104 switch (val->key) {
00105 case XMMS_STREAM_TYPE_MIMETYPE:
00106 case XMMS_STREAM_TYPE_URL:
00107 val->type = STRING;
00108 val->d.string = g_strdup (va_arg (ap, char *));
00109 break;
00110 case XMMS_STREAM_TYPE_FMT_FORMAT:
00111 case XMMS_STREAM_TYPE_FMT_CHANNELS:
00112 case XMMS_STREAM_TYPE_FMT_SAMPLERATE:
00113 val->type = INT;
00114 val->d.num = va_arg (ap, int);
00115 break;
00116 default:
00117 XMMS_DBG ("UNKNOWN TYPE!!");
00118 return NULL;
00119 }
00120 res->list = g_list_append (res->list, val);
00121 }
00122
00123 if (!res->name) {
00124 const gchar *mime = xmms_stream_type_get_str (res, XMMS_STREAM_TYPE_MIMETYPE);
00125 const gchar *url = xmms_stream_type_get_str (res, XMMS_STREAM_TYPE_URL);
00126
00127 if (mime && url) {
00128 res->name = g_strconcat (mime, ":", url, NULL);
00129 } else if (mime) {
00130 res->name = g_strdup (mime);
00131 } else {
00132 g_assert_not_reached ();
00133 }
00134
00135 g_strdelimit (res->name, ".", '_');
00136 }
00137
00138 if (res->priority < 0) {
00139 res->priority = XMMS_STREAM_TYPE_PRIORITY_DEFAULT;
00140 }
00141
00142 return res;
00143 }
00144
00145 const char *
00146 xmms_stream_type_get_str (const xmms_stream_type_t *st, xmms_stream_type_key_t key)
00147 {
00148 GList *n;
00149
00150 if (key == XMMS_STREAM_TYPE_NAME) {
00151 return st->name;
00152 }
00153
00154 for (n = st->list; n; n = g_list_next (n)) {
00155 xmms_stream_type_val_t *val = n->data;
00156 if (val->key == key) {
00157 if (val->type != STRING) {
00158 XMMS_DBG ("Key passed to get_str is not string");
00159 return NULL;
00160 }
00161 return val->d.string;
00162 }
00163 }
00164 return NULL;
00165 }
00166
00167
00168 gint
00169 xmms_stream_type_get_int (const xmms_stream_type_t *st, xmms_stream_type_key_t key)
00170 {
00171 GList *n;
00172
00173 if (key == XMMS_STREAM_TYPE_PRIORITY) {
00174 return st->priority;
00175 }
00176
00177 for (n = st->list; n; n = g_list_next (n)) {
00178 xmms_stream_type_val_t *val = n->data;
00179 if (val->key == key) {
00180 if (val->type != INT) {
00181 XMMS_DBG ("Key passed to get_int is not int");
00182 return -1;
00183 }
00184 return val->d.num;
00185 }
00186 }
00187 return -1;
00188 }
00189
00190
00191
00192
00193 static gboolean
00194 match_val (xmms_stream_type_val_t *vin, xmms_stream_type_val_t *vout)
00195 {
00196 if (vin->type != vout->type)
00197 return FALSE;
00198 switch (vin->type) {
00199 case STRING:
00200 return g_pattern_match_simple (vin->d.string, vout->d.string);
00201 case INT:
00202 return vin->d.num == vout->d.num;
00203 }
00204 return FALSE;
00205 }
00206
00207 gboolean
00208 xmms_stream_type_match (const xmms_stream_type_t *in_type, const xmms_stream_type_t *out_type)
00209 {
00210 GList *in;
00211
00212 for (in = in_type->list; in; in = g_list_next (in)) {
00213 xmms_stream_type_val_t *inval = in->data;
00214 GList *n;
00215
00216 for (n = out_type->list; n; n = g_list_next (n)) {
00217 xmms_stream_type_val_t *outval = n->data;
00218 if (inval->key == outval->key) {
00219 if (!match_val (inval, outval))
00220 return FALSE;
00221 break;
00222 }
00223
00224 }
00225 if (!n) {
00226
00227 return FALSE;
00228 }
00229 }
00230
00231 return TRUE;
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 xmms_stream_type_t *
00255 _xmms_stream_type_new (void *dumb, ...)
00256 {
00257 xmms_stream_type_t *res;
00258 va_list ap;
00259
00260 va_start (ap, dumb);
00261 res = xmms_stream_type_parse (ap);
00262 va_end (ap);
00263
00264 return res;
00265 }