mmore updates
[platform/upstream/gstreamer.git] / tools / gst-complete.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <sys/stat.h>
4
5 #include <gst/gstconfig.h>
6
7 #include <glib.h>
8
9
10 typedef struct {
11   gchar *name;
12   GSList *srcpads;
13   GSList *sinkpads;
14   GSList *srcpadtemplates;
15   GSList *sinkpadtemplates;
16   GSList *arguments;
17 } comp_element;
18
19 enum {
20   ARG_INT,
21   ARG_FILENAME,
22   ARG_ENUM
23 };
24
25 typedef struct {
26   gchar *name;
27   int type;
28   GSList *enums;
29 } comp_argument;
30
31 typedef struct {
32   gint value;
33   gchar *nick;
34 } enum_value;
35
36
37 void print_match_list (gchar *prefix, int len, GSList *wordlist) {
38   GSList *words = wordlist;
39
40   while (words) {
41     if (!len || !strncmp((gchar *)(words->data), prefix, len))
42       printf("%s\n",(gchar *)(words->data));
43     words = g_slist_next (words);
44   }
45 }
46
47 int match_element (comp_element *element, gchar *name) {
48   return strcmp(element->name,name);
49 }
50
51 int main(int argc,char *argv[]) {
52   xmlDocPtr doc;
53   xmlNodePtr rootnode, elementnode, propnode, argnode;
54   GList *element_list = NULL;
55   comp_element *element;
56   GSList *element_names = NULL;
57   comp_argument *argument;
58   enum_value *option;
59
60   gchar *prev_word = argv[3];
61   gchar *partial_word = argv[2];
62   int partial_len;
63   GList *elements;
64   GSList *pads;
65   int num_pads;
66   GSList *args;
67   gchar *word;
68   GSList *words = NULL;
69
70   struct stat stat_buf;
71   
72   partial_len = strlen(partial_word);
73
74   /***** Loading the completion information from the registry *****/
75
76   if (stat (GST_CONFIG_DIR"/compreg.xml", &stat_buf) == 0) {
77     doc = xmlParseFile (GST_CONFIG_DIR"/compreg.xml");
78   } else {
79     exit (1);
80   }
81   rootnode = doc->xmlRootNode;
82
83   elementnode = rootnode->xmlChildrenNode;
84   while (elementnode) {
85     if (!strcmp(elementnode->name, "element")) {
86       element = g_new0(comp_element,1);
87       propnode = elementnode->xmlChildrenNode;
88       while (propnode) {
89
90         if (!strcmp(propnode->name, "name")) {
91           element->name = xmlNodeGetContent(propnode);
92 /* fprintf(stderr,element->name); */
93         } else if (!strcmp(propnode->name, "srcpad")) {
94           element->srcpads = g_slist_prepend(element->srcpads, xmlNodeGetContent(propnode));
95 /* fprintf(stderr,"."); */
96         } else if (!strcmp(propnode->name, "sinkpad")) {
97           element->sinkpads = g_slist_prepend(element->sinkpads, xmlNodeGetContent(propnode));
98         } else if (!strcmp(propnode->name, "srcpadtemplate")) {
99           element->srcpadtemplates = g_slist_prepend(element->srcpadtemplates, xmlNodeGetContent(propnode));
100 /* fprintf(stderr,"."); */
101         } else if (!strcmp(propnode->name, "sinkpad")) {
102           element->sinkpadtemplates = g_slist_prepend(element->sinkpadtemplates, xmlNodeGetContent(propnode));
103         } else if (!strcmp(propnode->name, "argument")) {
104           argument = g_new0(comp_argument,1);
105           argument->name = xmlNodeGetContent(propnode);
106           argument->type = ARG_INT;
107
108           /* walk through the values data */
109           argnode = propnode->xmlChildrenNode;
110           while (argnode) {
111             if (!strcmp(argnode->name, "filename")) {
112               argument->type = ARG_FILENAME;
113             } else if (!strcmp(argnode->name,"option")) {
114               argument->type = ARG_ENUM;
115               option = g_new0(enum_value,1);
116               sscanf(xmlNodeGetContent(argnode),"%d",&option->value);
117               argument->enums = g_slist_prepend (argument->enums, option);
118             }
119             argnode = argnode->next;
120           }
121
122           element->arguments = g_slist_prepend(element->arguments, argument);
123         }
124
125         propnode = propnode->next;
126       }
127       element_list = g_list_prepend(element_list, element);
128       element_names = g_slist_prepend(element_names, element->name);
129     }
130     elementnode = elementnode->next;
131   }
132
133
134
135   /***** Completion *****/
136
137   /* The bulk of the work is in deciding exactly which words are an option. */
138
139   /* if we're right at the beginning, with -launch in the first word */
140   if (strstr(prev_word,"-launch")) {
141     /* print out only elements with no sink pad or padtemplate */
142     elements = element_list;
143     while (elements) {
144       element = (comp_element *)(elements->data);
145       if (!element->sinkpads && !element->sinkpadtemplates)
146         words = g_slist_prepend (words, element->name);
147       elements = g_list_next(elements);
148     }
149   }
150
151   /* if the previous word is a connection */
152   if (strchr(prev_word, '!')) {
153     /* print out oly elements with a sink pad or template */
154     elements = element_list;
155     while (elements) {
156       element = (comp_element *)(elements->data);
157       if (element->sinkpads || element->sinkpadtemplates)
158         words = g_slist_prepend (words, element->name);
159       elements = g_list_next (elements);
160     }
161   }
162
163   /* if the partial word is an argument, and it's an enum */
164   if (strchr(prev_word,'=')) {
165     fprintf(stderr,"it's an arg, but dunno what element yet\n");
166   }
167
168   /* if the previous word is an element, we need to list both pads and arguments*/
169   if ((elements = g_list_find_custom(element_list, prev_word, (GCompareFunc)match_element))) {
170     element = elements->data;
171     /* zero the numpads list so we can count them */
172     num_pads = 0;
173
174     /* pads */
175     pads = element->srcpads;
176     while (pads) {
177       num_pads++;
178       words = g_slist_prepend (words, g_strdup_printf("%s!",(gchar *)(pads->data)));
179       pads = g_slist_next (pads);
180     }
181
182     /* padtemplates */
183     pads = element->srcpadtemplates;
184     while (pads) {
185       num_pads++;
186       word = g_strdup_printf("%s!",(gchar *)(pads->data));
187       if (!g_slist_find_custom(words,word,(GCompareFunc)strcmp))
188         words = g_slist_prepend (words, word);
189       pads = g_slist_next (pads);
190     }
191
192     /* if there is only one pad, add '!' to the list of completions */
193     if (num_pads == 1) {
194       words = g_slist_prepend (words, "!");
195     }
196
197     /* arguments */
198     args = element->arguments;
199     while (args) {
200       argument = (comp_argument *)(args->data);
201       word = strstr(argument->name,"::")+2;
202       words = g_slist_prepend (words, g_strdup_printf("%s=",word));
203       words = g_slist_prepend (words, g_strdup_printf("%s=...",word));
204       args = g_slist_next (args);
205     }
206   }
207
208
209   /* The easy part is ouptuting the correct list of possibilities. */
210   print_match_list (partial_word, partial_len, words);
211
212   return 0;
213 }