tools: remove unversioned gst-launch, gst-inspect and gst-typefind

The unversioned tool wrappers are confusing and annoying for packagers,
users and developers alike. A gst-launch pipeline that works in 0.10
will likely not work in 0.11 (e.g. because elements or properties get
renamed, or syntax changes). The unversioned tools also yield useless
results when used with gdb or valgrind. Packagers need to co-ordinate
the packaging of all major versions to make sure there are no conflicts
when both try to install the same files. When two major versions are
in use (e.g. 0.10 and 0.11/1.0), it may be unclear (when looking at
things on IRC/pastebin/mailing list etc.) which version is actually
being used when there are unversioned wrappers. For all these reasons,
it seems best to just remove them for now.
This commit is contained in:
Tim-Philipp Müller 2011-06-05 14:10:50 +01:00
parent ae23ae1c8b
commit accfb89ea8
2 changed files with 13 additions and 467 deletions

View file

@ -1,83 +1,46 @@
### assemble a list of programs we want to build and install
if GST_DISABLE_PARSE
GST_PARSE_SRC =
GST_PARSE_SRC_V =
else
GST_PARSE_SRC = gst-launch
GST_PARSE_SRC_V = gst-launch-@GST_MAJORMINOR@
endif
GST_OTHER_SRC = \
gst-inspect \
gst-typefind
GST_OTHER_SRC_V = \
bin_PROGRAMS = \
gst-inspect-@GST_MAJORMINOR@ \
gst-typefind-@GST_MAJORMINOR@
### so all of the programs we want to build
bin_PROGRAMS = \
$(GST_PARSE_SRC) $(GST_PARSE_SRC_V) \
$(GST_OTHER_SRC) $(GST_OTHER_SRC_V)
# make sure each versioned tool has the right source file and flags
if !GST_DISABLE_PARSE
gst_launch_@GST_MAJORMINOR@_SOURCES = gst-launch.c tools.h
gst_launch_@GST_MAJORMINOR@_CFLAGS = $(GST_OBJ_CFLAGS) -UGST_DISABLE_DEPRECATED
gst_launch_@GST_MAJORMINOR@_LDADD = $(GST_OBJ_LIBS)
endif
gst_inspect_@GST_MAJORMINOR@_SOURCES = gst-inspect.c tools.h
gst_inspect_@GST_MAJORMINOR@_CFLAGS = $(GST_OBJ_CFLAGS)
gst_inspect_@GST_MAJORMINOR@_LDADD = $(GST_OBJ_LIBS)
gst_typefind_@GST_MAJORMINOR@_SOURCES = gst-typefind.c tools.h
gst_typefind_@GST_MAJORMINOR@_CFLAGS = $(GST_OBJ_CFLAGS)
gst_typefind_@GST_MAJORMINOR@_LDADD = $(GST_OBJ_LIBS)
# make sure each unversioned tool comes from gst-run.c
if !GST_DISABLE_PARSE
gst_launch_SOURCES = gst-run.c
bin_PROGRAMS += gst-launch-@GST_MAJORMINOR@
gst_launch_@GST_MAJORMINOR@_SOURCES = gst-launch.c tools.h
gst_launch_@GST_MAJORMINOR@_CFLAGS = $(GST_OBJ_CFLAGS)
gst_launch_@GST_MAJORMINOR@_LDADD = $(GST_OBJ_LIBS)
endif
gst_inspect_SOURCES = gst-run.c
gst_typefind_SOURCES = gst-run.c
# CFLAGS and libs for nonversioned frontend binaries
AM_CFLAGS = $(GLIB_ONLY_CFLAGS)
LDADD = $(GLIB_ONLY_LIBS)
# due to depcomp not using AM_CFLAGS for rh9/yd3, we also set AM_CPPFLAGS
AM_CPPFLAGS = $(GLIB_ONLY_CFLAGS)
Android.mk: Makefile.am
androgenizer -:PROJECT gstreamer \
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-:EXECUTABLE gst-inspect -:TAGS eng debug \
-:EXECUTABLE gst-inspect-@GST_MAJORMINOR@ -:TAGS eng debug \
-:SOURCES $(gst_inspect_@GST_MAJORMINOR@_SOURCES) \
-:CFLAGS $(DEFS) $(gst_inspect_@GST_MAJORMINOR@_CFLAGS) \
-:LDFLAGS $(gst_inspect_@GST_MAJORMINOR@_LDADD) \
-:PASSTHROUGH LOCAL_ARM_MODE:=arm \
-:EXECUTABLE gst-launch -:TAGS eng debug \
-:EXECUTABLE gst-launch-@GST_MAJORMINOR@ -:TAGS eng debug \
-:SOURCES $(gst_launch_@GST_MAJORMINOR@_SOURCES) \
-:CFLAGS $(DEFS) $(gst_launch_@GST_MAJORMINOR@_CFLAGS) \
-:LDFLAGS $(gst_launch_@GST_MAJORMINOR@_LDADD) \
-:PASSTHROUGH LOCAL_ARM_MODE:=arm \
> $@
### man pages we want to install
if GST_DISABLE_PARSE
GST_PARSE_MAN=
else
GST_PARSE_MAN = \
gst-launch-@GST_MAJORMINOR@.1
endif
GST_OTHER_MAN = \
manpages = \
gst-inspect-@GST_MAJORMINOR@.1 \
gst-typefind-@GST_MAJORMINOR@.1
manpages = $(GST_PARSE_MAN) $(GST_OTHER_MAN)
if !GST_DISABLE_PARSE
manpages += gst-launch-@GST_MAJORMINOR@.1
endif
CLEANFILES = $(manpages) *.gcno *.gcda
man_MANS = $(manpages)

View file

@ -1,417 +0,0 @@
/* GStreamer
* Copyright (C) 2004 Thomas Vander Stichele <thomas@apestaart.org>
*
* gst-run.c: tool to launch GStreamer tools with correct major/minor
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <errno.h>
#include <glib.h>
/* global statics for option parsing */
static gboolean _print = FALSE;
static gchar *_arg_mm = NULL;
static gboolean _arg_list_mm = FALSE;
/* popt options table for the wrapper */
static GOptionEntry wrapper_options[] = {
{"print", 'p', 0, G_OPTION_ARG_NONE, &_print,
"print wrapped command line options", NULL},
{"gst-mm", 0, 0, G_OPTION_ARG_STRING, &_arg_mm,
"Force major/minor version", "VERSION"},
{"gst-list-mm", 0, 0, G_OPTION_ARG_NONE, &_arg_list_mm,
"List found major/minor versions", NULL},
{NULL}
};
/* print out the major/minor, which is the hash key */
static void
hash_print_key (gchar * key, gchar * value)
{
g_print ("%s\n", (gchar *) key);
}
/* return value like strcmp, but compares major/minor numerically */
static gint
compare_major_minor (const gchar * first, const gchar * second)
{
gchar **firsts, **seconds;
gint fmaj, fmin, smaj, smin;
gint ret = 0;
firsts = g_strsplit (first, ".", 0);
seconds = g_strsplit (second, ".", 0);
if (firsts[0] == NULL || firsts[1] == NULL) {
ret = -1;
goto beach;
}
if (seconds[0] == NULL || seconds[1] == NULL) {
ret = 1;
goto beach;
}
fmaj = atoi (firsts[0]);
fmin = atoi (firsts[1]);
smaj = atoi (seconds[0]);
smin = atoi (seconds[1]);
if (fmaj < smaj) {
ret = -1;
goto beach;
}
if (fmaj > smaj) {
ret = 1;
goto beach;
}
/* fmaj == smaj */
if (fmin < smin) {
ret = -1;
goto beach;
}
if (fmin > smin) {
ret = 1;
goto beach;
}
ret = 0;
beach:
g_strfreev (firsts);
g_strfreev (seconds);
return ret;
}
static void
find_highest_version (gchar * key, gchar * value, gchar ** highest)
{
if (*highest == NULL) {
/* first value, so just set it */
*highest = key;
}
if (compare_major_minor (key, *highest) > 0)
*highest = key;
}
/* Libtool creates shell scripts named "base" that calls actual binaries as
* .libs/lt-base. If we detect this is a libtool script, unmangle so we
* find the right binaries */
static void
unmangle_libtool (gchar ** dir, gchar ** base)
{
gchar *new_dir, *new_base;
if (!*dir)
return;
if (!*base)
return;
/* We assume libtool when base starts with "lt-" and dir ends with ".libs".
* On Windows libtool doesn't seem to be adding "lt-" prefix. */
#ifndef G_OS_WIN32
if (!g_str_has_prefix (*base, "lt-"))
return;
#endif
if (!g_str_has_suffix (*dir, ".libs"))
return;
#ifndef G_OS_WIN32
new_base = g_strdup (&((*base)[3]));
#else
new_base = g_strdup (*base);
#endif
new_dir = g_path_get_dirname (*dir);
g_free (*base);
g_free (*dir);
*base = new_base;
*dir = new_dir;
}
/* Returns a directory path that contains the binary given as an argument.
* If the binary given contains a path, it gets looked for in that path.
* If it doesn't contain a path, it gets looked for in the standard path.
*
* The returned string is newly allocated.
*/
static gchar *
get_dir_of_binary (const gchar * binary)
{
gchar *base, *dir;
gchar *full;
base = g_path_get_basename (binary);
dir = g_path_get_dirname (binary);
/* if putting these two together yields the same as binary,
* then we have the right breakup. If not, it's because no path was
* specified which caused get_basename to return "." */
full = g_build_filename (dir, base, NULL);
#ifdef G_OS_WIN32
/* g_build_filename() should be using the last path separator used in the
* input according to the docs, but doesn't actually do that, so we have
* to fix up the result. */
{
gchar *tmp;
for (tmp = (gchar *) binary + strlen (binary) - 1; tmp >= binary; tmp--) {
if (*tmp == '/' || *tmp == '\\') {
full[strlen (dir)] = *tmp;
break;
}
}
}
#endif
if (strcmp (full, binary) != 0) {
if (strcmp (dir, ".") != 0) {
g_warning ("This should not happen, g_path_get_dirname () has changed.");
g_free (base);
g_free (dir);
g_free (full);
return NULL;
}
/* we know no path was specified, so search standard path for binary */
g_free (full);
full = g_find_program_in_path (base);
if (!full) {
g_warning ("This should not happen, %s not in standard path.", base);
g_free (base);
g_free (dir);
return NULL;
}
}
g_free (base);
g_free (dir);
dir = g_path_get_dirname (full);
g_free (full);
return dir;
}
/* Search the given directory for candidate binaries matching the base binary.
* Return a GHashTable of major/minor -> directory pairs
*/
static GHashTable *
get_candidates (const gchar * dir, const gchar * base)
{
GDir *gdir;
GError *error = NULL;
const gchar *entry;
gchar *path;
gchar *suffix, *copy;
gchar *pattern;
GPatternSpec *spec, *specexe;
gchar **dirs;
gchar **cur;
GHashTable *candidates = NULL;
candidates = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
/* compile our pattern specs */
pattern = g_strdup_printf ("%s-*.*", base);
spec = g_pattern_spec_new (pattern);
g_free (pattern);
pattern = g_strdup_printf ("%s-*.*.exe", base);
specexe = g_pattern_spec_new (pattern);
g_free (pattern);
/* get all dirs from the path and prepend with given dir */
if (dir)
path = g_strdup_printf ("%s%c%s",
dir, G_SEARCHPATH_SEPARATOR, g_getenv ("PATH"));
else
path = (gchar *) g_getenv ("PATH");
dirs = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 0);
if (dir)
g_free (path);
/* check all of these in reverse order by winding to bottom and going up */
cur = &dirs[0];
while (*cur)
++cur;
while (cur != &dirs[0]) {
--cur;
if (!g_file_test (*cur, G_FILE_TEST_EXISTS) ||
!g_file_test (*cur, G_FILE_TEST_IS_DIR)) {
continue;
}
gdir = g_dir_open (*cur, 0, &error);
if (!gdir) {
g_warning ("Could not open dir %s: %s", *cur, error->message);
g_error_free (error);
return NULL;
}
while ((entry = g_dir_read_name (gdir))) {
if (g_pattern_match_string (spec, entry)
|| g_pattern_match_string (specexe, entry)) {
gchar *full;
/* is it executable ? */
full = g_build_filename (*cur, entry, NULL);
if (!g_file_test (full, G_FILE_TEST_IS_EXECUTABLE)) {
g_free (full);
continue;
}
g_free (full);
/* strip base and dash from it */
suffix = g_strdup (&(entry[strlen (base) + 1]));
copy = g_strdup (suffix);
/* strip possible .exe from copy */
if (g_strrstr (copy, ".exe"))
g_strrstr (copy, ".exe")[0] = '\0';
/* stricter pattern check: check if it only contains digits or dots */
g_strcanon (copy, "0123456789.", 'X');
if (strstr (copy, "X")) {
g_free (suffix);
g_free (copy);
continue;
}
g_free (copy);
g_hash_table_insert (candidates, suffix, g_strdup (*cur));
}
}
}
g_strfreev (dirs);
g_pattern_spec_free (spec);
return candidates;
}
int
main (int argc, char **argv)
{
GHashTable *candidates;
gchar *dir;
gchar *base;
gchar *highest = NULL;
gchar *binary; /* actual binary we're going to run */
gchar *path = NULL; /* and its path */
gchar *desc;
GOptionContext *ctx;
GError *err = NULL;
/* detect stuff */
dir = get_dir_of_binary (argv[0]);
base = g_path_get_basename (argv[0]);
/* parse command line options */
desc = g_strdup_printf ("wrapper to call versioned %s", base);
ctx = g_option_context_new (desc);
g_free (desc);
g_option_context_set_ignore_unknown_options (ctx, TRUE);
g_option_context_add_main_entries (ctx, wrapper_options, GETTEXT_PACKAGE);
if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
g_print ("Error initializing: %s\n", err->message);
exit (1);
}
g_option_context_free (ctx);
/* unmangle libtool if necessary */
unmangle_libtool (&dir, &base);
#ifdef G_OS_WIN32
/* remove .exe suffix, otherwise we'll be looking for gst-blah.exe-*.* */
if (strlen (base) > 4 && g_str_has_suffix (base, ".exe")) {
base[strlen (base) - 4] = '\0';
}
#endif
/* get all candidate binaries */
candidates = get_candidates (dir, base);
g_free (dir);
if (_arg_mm) {
/* if a version was forced, look it up in the hash table */
dir = g_hash_table_lookup (candidates, _arg_mm);
if (!dir) {
g_print ("ERROR: Major/minor %s of tool %s not found.\n", _arg_mm, base);
return 1;
}
binary = g_strdup_printf ("%s-%s", base, _arg_mm);
} else {
highest = NULL;
/* otherwise, just look up the highest version */
if (candidates) {
g_hash_table_foreach (candidates, (GHFunc) find_highest_version,
&highest);
}
if (highest == NULL) {
g_print ("ERROR: No version of tool %s found.\n", base);
return 1;
}
dir = g_hash_table_lookup (candidates, highest);
binary = g_strdup_printf ("%s-%s", base, highest);
}
g_free (base);
path = g_build_filename (dir, binary, NULL);
g_free (binary);
/* print out list of major/minors we found if asked for */
/* FIXME: do them in order by creating a GList of keys and sort them */
if (_arg_list_mm) {
g_hash_table_foreach (candidates, (GHFunc) hash_print_key, NULL);
g_hash_table_destroy (candidates);
return 0;
}
/* print out command line if asked for */
argv[0] = path;
if (_print) {
int i;
for (i = 0; i < argc; ++i) {
g_print ("%s", argv[i]);
if (i < argc - 1)
g_print (" ");
}
g_print ("\n");
}
/* execute */
if (execv (path, argv) == -1) {
g_warning ("Error executing %s: %s (%d)", path, g_strerror (errno), errno);
}
g_free (path);
return 0;
}