source: trunk/third/gstreamer/tools/gst-complete.c @ 18714

Revision 18714, 6.2 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18713, which included commits to RCS files with non-trunk default branches.
Line 
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
10typedef struct {
11  gchar *name;
12  GSList *srcpads;
13  GSList *sinkpads;
14  GSList *srcpadtemplates;
15  GSList *sinkpadtemplates;
16  GSList *arguments;
17} comp_element;
18
19enum {
20  ARG_INT,
21  ARG_FILENAME,
22  ARG_ENUM
23};
24
25typedef struct {
26  gchar *name;
27  int type;
28  GSList *enums;
29} comp_argument;
30
31typedef struct {
32  gint value;
33  gchar *nick;
34} enum_value;
35
36
37void 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
47int match_element (comp_element *element, gchar *name) {
48  return strcmp(element->name,name);
49}
50
51int 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}
Note: See TracBrowser for help on using the repository browser.