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; |
---|
61 | gchar *partial_word; |
---|
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 | if(argc<4){ |
---|
73 | fprintf(stderr,"gst-complete called with invalid arguments\n"); |
---|
74 | exit(1); |
---|
75 | } |
---|
76 | |
---|
77 | prev_word = argv[3]; |
---|
78 | partial_word = argv[2]; |
---|
79 | |
---|
80 | partial_len = strlen(partial_word); |
---|
81 | |
---|
82 | /***** Loading the completion information from the registry *****/ |
---|
83 | |
---|
84 | if (stat (GST_CACHE_DIR"/compreg.xml", &stat_buf) == 0) { |
---|
85 | doc = xmlParseFile (GST_CACHE_DIR"/compreg.xml"); |
---|
86 | } else { |
---|
87 | exit (1); |
---|
88 | } |
---|
89 | rootnode = doc->xmlRootNode; |
---|
90 | |
---|
91 | elementnode = rootnode->xmlChildrenNode; |
---|
92 | while (elementnode) { |
---|
93 | if (!strcmp(elementnode->name, "element")) { |
---|
94 | element = g_new0(comp_element,1); |
---|
95 | propnode = elementnode->xmlChildrenNode; |
---|
96 | while (propnode) { |
---|
97 | |
---|
98 | if (!strcmp(propnode->name, "name")) { |
---|
99 | element->name = xmlNodeGetContent(propnode); |
---|
100 | /* fprintf(stderr,element->name); */ |
---|
101 | } else if (!strcmp(propnode->name, "srcpad")) { |
---|
102 | element->srcpads = g_slist_prepend(element->srcpads, xmlNodeGetContent(propnode)); |
---|
103 | /* fprintf(stderr,"."); */ |
---|
104 | } else if (!strcmp(propnode->name, "sinkpad")) { |
---|
105 | element->sinkpads = g_slist_prepend(element->sinkpads, xmlNodeGetContent(propnode)); |
---|
106 | } else if (!strcmp(propnode->name, "srcpadtemplate")) { |
---|
107 | element->srcpadtemplates = g_slist_prepend(element->srcpadtemplates, xmlNodeGetContent(propnode)); |
---|
108 | /* fprintf(stderr,"."); */ |
---|
109 | } else if (!strcmp(propnode->name, "sinkpad")) { |
---|
110 | element->sinkpadtemplates = g_slist_prepend(element->sinkpadtemplates, xmlNodeGetContent(propnode)); |
---|
111 | } else if (!strcmp(propnode->name, "argument")) { |
---|
112 | argument = g_new0(comp_argument,1); |
---|
113 | argument->name = xmlNodeGetContent(propnode); |
---|
114 | argument->type = ARG_INT; |
---|
115 | |
---|
116 | /* walk through the values data */ |
---|
117 | argnode = propnode->xmlChildrenNode; |
---|
118 | while (argnode) { |
---|
119 | if (!strcmp(argnode->name, "filename")) { |
---|
120 | argument->type = ARG_FILENAME; |
---|
121 | } else if (!strcmp(argnode->name,"option")) { |
---|
122 | argument->type = ARG_ENUM; |
---|
123 | option = g_new0(enum_value,1); |
---|
124 | sscanf(xmlNodeGetContent(argnode),"%d",&option->value); |
---|
125 | argument->enums = g_slist_prepend (argument->enums, option); |
---|
126 | } |
---|
127 | argnode = argnode->next; |
---|
128 | } |
---|
129 | |
---|
130 | element->arguments = g_slist_prepend(element->arguments, argument); |
---|
131 | } |
---|
132 | |
---|
133 | propnode = propnode->next; |
---|
134 | } |
---|
135 | element_list = g_list_prepend(element_list, element); |
---|
136 | element_names = g_slist_prepend(element_names, element->name); |
---|
137 | } |
---|
138 | elementnode = elementnode->next; |
---|
139 | } |
---|
140 | |
---|
141 | |
---|
142 | |
---|
143 | /***** Completion *****/ |
---|
144 | |
---|
145 | /* The bulk of the work is in deciding exactly which words are an option. */ |
---|
146 | |
---|
147 | /* if we're right at the beginning, with -launch in the first word */ |
---|
148 | if (strstr(prev_word,"-launch")) { |
---|
149 | /* print out only elements with no sink pad or padtemplate */ |
---|
150 | elements = element_list; |
---|
151 | while (elements) { |
---|
152 | element = (comp_element *)(elements->data); |
---|
153 | if (!element->sinkpads && !element->sinkpadtemplates) |
---|
154 | words = g_slist_prepend (words, element->name); |
---|
155 | elements = g_list_next(elements); |
---|
156 | } |
---|
157 | } |
---|
158 | |
---|
159 | /* if the previous word is a connection */ |
---|
160 | if (strchr(prev_word, '!')) { |
---|
161 | /* print out oly elements with a sink pad or template */ |
---|
162 | elements = element_list; |
---|
163 | while (elements) { |
---|
164 | element = (comp_element *)(elements->data); |
---|
165 | if (element->sinkpads || element->sinkpadtemplates) |
---|
166 | words = g_slist_prepend (words, element->name); |
---|
167 | elements = g_list_next (elements); |
---|
168 | } |
---|
169 | } |
---|
170 | |
---|
171 | /* if the partial word is an argument, and it's an enum */ |
---|
172 | if (strchr(prev_word,'=')) { |
---|
173 | fprintf(stderr,"it's an arg, but dunno what element yet\n"); |
---|
174 | } |
---|
175 | |
---|
176 | /* if the previous word is an element, we need to list both pads and arguments*/ |
---|
177 | if ((elements = g_list_find_custom(element_list, prev_word, (GCompareFunc)match_element))) { |
---|
178 | element = elements->data; |
---|
179 | /* zero the numpads list so we can count them */ |
---|
180 | num_pads = 0; |
---|
181 | |
---|
182 | /* pads */ |
---|
183 | pads = element->srcpads; |
---|
184 | while (pads) { |
---|
185 | num_pads++; |
---|
186 | words = g_slist_prepend (words, g_strdup_printf("%s!",(gchar *)(pads->data))); |
---|
187 | pads = g_slist_next (pads); |
---|
188 | } |
---|
189 | |
---|
190 | /* padtemplates */ |
---|
191 | pads = element->srcpadtemplates; |
---|
192 | while (pads) { |
---|
193 | num_pads++; |
---|
194 | word = g_strdup_printf("%s!",(gchar *)(pads->data)); |
---|
195 | if (!g_slist_find_custom(words,word,(GCompareFunc)strcmp)) |
---|
196 | words = g_slist_prepend (words, word); |
---|
197 | pads = g_slist_next (pads); |
---|
198 | } |
---|
199 | |
---|
200 | /* if there is only one pad, add '!' to the list of completions */ |
---|
201 | if (num_pads == 1) { |
---|
202 | words = g_slist_prepend (words, "!"); |
---|
203 | } |
---|
204 | |
---|
205 | /* arguments */ |
---|
206 | args = element->arguments; |
---|
207 | while (args) { |
---|
208 | argument = (comp_argument *)(args->data); |
---|
209 | word = strstr(argument->name,"::")+2; |
---|
210 | words = g_slist_prepend (words, g_strdup_printf("%s=",word)); |
---|
211 | words = g_slist_prepend (words, g_strdup_printf("%s=...",word)); |
---|
212 | args = g_slist_next (args); |
---|
213 | } |
---|
214 | } |
---|
215 | |
---|
216 | |
---|
217 | /* The easy part is ouptuting the correct list of possibilities. */ |
---|
218 | print_match_list (partial_word, partial_len, words); |
---|
219 | |
---|
220 | return 0; |
---|
221 | } |
---|