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

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