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