You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
383 lines
10 KiB
383 lines
10 KiB
/*
|
|
* tcmodinfo.c
|
|
*
|
|
* Copyright (C) Tilmann Bitterberg - August 2002
|
|
* updated and partially rewritten by
|
|
* Copyright (C) Francesco Romani - January 2006
|
|
*
|
|
* This file is part of transcode, a video stream processing tool
|
|
*
|
|
* transcode is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* transcode 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GNU Make; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "tcstub.h"
|
|
|
|
#define EXE "tcmodinfo"
|
|
|
|
enum {
|
|
STATUS_OK = 0,
|
|
STATUS_BAD_PARAM,
|
|
STATUS_NO_MODULE,
|
|
STATUS_MODULE_ERROR,
|
|
STATUS_NO_SOCKET,
|
|
STATUS_SOCKET_ERROR,
|
|
STATUS_BAD_MODULES,
|
|
STATUS_MODULE_FAILED,
|
|
};
|
|
|
|
void version(void)
|
|
{
|
|
printf("%s (%s v%s) (C) 2001-2010 Tilmann Bitterberg, "
|
|
"Transcode Team\n", EXE, PACKAGE, VERSION);
|
|
}
|
|
|
|
static void usage(void)
|
|
{
|
|
version();
|
|
tc_log_info(EXE, "Usage: %s [options]", EXE);
|
|
fprintf(stderr, " -i name Module name information (like \'smooth\')\n");
|
|
fprintf(stderr, " -p Print the compiled-in module path\n");
|
|
fprintf(stderr, " -d verbosity Verbosity mode [1 == TC_INFO]\n");
|
|
#ifdef ENABLE_EXPERIMENTAL
|
|
fprintf(stderr, " -m path Use PATH as module path\n");
|
|
fprintf(stderr, " -M element Request to module informations about <element>\n");
|
|
fprintf(stderr, " -C string Request to configure module using configuration <string>\n");
|
|
fprintf(stderr, " -t type Type of module (filter, encode, multiplex)\n");
|
|
#endif
|
|
fprintf(stderr, " -s socket Connect to transcode socket\n");
|
|
fprintf(stderr, "\n");
|
|
}
|
|
|
|
static int do_connect_socket(const char *socketfile)
|
|
{
|
|
int sock, retval;
|
|
struct sockaddr_un server;
|
|
char buf[OPTS_SIZE];
|
|
fd_set rfds;
|
|
struct timeval tv;
|
|
ssize_t n;
|
|
|
|
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
if (sock < 0) {
|
|
perror("opening stream socket");
|
|
return STATUS_NO_SOCKET;
|
|
}
|
|
server.sun_family = AF_UNIX;
|
|
strlcpy(server.sun_path, socketfile, sizeof(server.sun_path));
|
|
|
|
if (connect(sock, (struct sockaddr *) &server,
|
|
sizeof(struct sockaddr_un)) < 0) {
|
|
close(sock);
|
|
perror("connecting stream socket");
|
|
return STATUS_NO_SOCKET;
|
|
}
|
|
|
|
while (1) {
|
|
/* Watch stdin (fd 0) to see when it has input. */
|
|
FD_ZERO(&rfds);
|
|
FD_SET(0, &rfds); // stdin
|
|
FD_SET(sock, &rfds);
|
|
/* Wait up to five seconds. */
|
|
tv.tv_sec = 5;
|
|
tv.tv_usec = 0;
|
|
|
|
retval = select(sock+1, &rfds, NULL, NULL, NULL);
|
|
/* Don't rely on the value of tv now! */
|
|
|
|
memset(buf, 0, sizeof (buf)); // null-termination in advance, slowly
|
|
|
|
if (retval>0) {
|
|
if (FD_ISSET(0, &rfds)) {
|
|
fgets(buf, OPTS_SIZE, stdin);
|
|
}
|
|
if (FD_ISSET(sock, &rfds)) {
|
|
if ( (n = read(sock, buf, OPTS_SIZE)) < 0) {
|
|
perror("reading on stream socket");
|
|
break;
|
|
} else if (n == 0) { // EOF
|
|
fprintf (stderr, "Server closed connection\n");
|
|
break;
|
|
}
|
|
printf("%s", buf);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (write(sock, buf, strlen(buf)) < 0)
|
|
perror("writing on stream socket");
|
|
|
|
memset(buf, 0, sizeof (buf));
|
|
|
|
if (read(sock, buf, OPTS_SIZE) < 0)
|
|
perror("reading on stream socket");
|
|
|
|
printf("%s", buf);
|
|
|
|
if (!isatty(0))
|
|
break;
|
|
}
|
|
|
|
close(sock);
|
|
return STATUS_OK;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int ch;
|
|
const char *filename = NULL;
|
|
const char *modpath = MOD_PATH;
|
|
#ifdef ENABLE_EXPERIMENTAL
|
|
const char *modtype = "filter";
|
|
const char *modarg = ""; /* nothing */
|
|
const char *modcfg = ""; /* nothing */
|
|
#endif
|
|
const char *socketfile = NULL;
|
|
char options[OPTS_SIZE] = { '\0', };
|
|
int print_mod = 0;
|
|
int connect_socket = 0;
|
|
int ret = 0;
|
|
int status = STATUS_NO_MODULE;
|
|
|
|
/* needed by filter modules */
|
|
TCVHandle tcv_handle = tcv_init();
|
|
#ifdef ENABLE_EXPERIMENTAL
|
|
TCFactory factory = NULL;
|
|
TCModule module = NULL;
|
|
#endif
|
|
|
|
vframe_list_t ptr;
|
|
|
|
memset(&ptr, 0, sizeof(ptr));
|
|
|
|
ac_init(AC_ALL);
|
|
tc_set_config_dir(NULL);
|
|
|
|
if (argc == 1) {
|
|
usage();
|
|
return STATUS_BAD_PARAM;
|
|
}
|
|
|
|
libtc_init(&argc, &argv);
|
|
|
|
while (1) {
|
|
#ifdef ENABLE_EXPERIMENTAL
|
|
ch = getopt(argc, argv, "C:d:i:?vhpm:M:s:t:");
|
|
#else /* !ENABLE_EXPERIMENTAL */
|
|
ch = getopt(argc, argv, "d:i:?vhps:");
|
|
#endif
|
|
if (ch == -1) {
|
|
break;
|
|
}
|
|
|
|
switch (ch) {
|
|
case 'd':
|
|
if (optarg[0] == '-') {
|
|
usage();
|
|
return STATUS_BAD_PARAM;
|
|
}
|
|
verbose = atoi(optarg);
|
|
break;
|
|
case 'i':
|
|
if (optarg[0] == '-') {
|
|
usage();
|
|
return STATUS_BAD_PARAM;
|
|
}
|
|
filename = optarg;
|
|
break;
|
|
#ifdef ENABLE_EXPERIMENTAL
|
|
case 'C':
|
|
modcfg = optarg;
|
|
break;
|
|
case 'm':
|
|
modpath = optarg;
|
|
break;
|
|
case 'M':
|
|
modarg = optarg;
|
|
break;
|
|
case 't':
|
|
if (!optarg) {
|
|
usage();
|
|
return STATUS_BAD_PARAM;
|
|
}
|
|
if (!strcmp(optarg, "filter")
|
|
|| !strcmp(optarg, "encode")
|
|
|| !strcmp(optarg, "multiplex")) {
|
|
modtype = optarg;
|
|
} else {
|
|
modtype = NULL;
|
|
}
|
|
break;
|
|
#endif
|
|
case 's':
|
|
if (optarg[0] == '-') {
|
|
usage();
|
|
return STATUS_BAD_PARAM;
|
|
}
|
|
connect_socket = 1;
|
|
socketfile = optarg;
|
|
break;
|
|
case 'p':
|
|
print_mod = 1;
|
|
break;
|
|
case 'v':
|
|
version();
|
|
return STATUS_OK;
|
|
case '?': /* fallthrough */
|
|
case 'h': /* fallthrough */
|
|
default:
|
|
usage();
|
|
return STATUS_OK;
|
|
}
|
|
}
|
|
|
|
if (print_mod) {
|
|
printf("%s\n", modpath);
|
|
return STATUS_OK;
|
|
}
|
|
|
|
if (connect_socket) {
|
|
do_connect_socket(socketfile);
|
|
return STATUS_OK;
|
|
}
|
|
|
|
if (!filename) {
|
|
usage();
|
|
return STATUS_BAD_PARAM;
|
|
}
|
|
|
|
#ifdef ENABLE_EXPERIMENTAL
|
|
if (!modtype || !strcmp(modtype, "import")) {
|
|
tc_log_error(EXE, "Unknown module type (not in filter, encode, multiplex)");
|
|
return STATUS_BAD_PARAM;
|
|
}
|
|
|
|
if (strlen(modcfg) > 0 && strlen(modarg) > 0) {
|
|
tc_log_error(EXE, "Cannot configure and inspect module on the same time");
|
|
return STATUS_BAD_PARAM;
|
|
}
|
|
|
|
/*
|
|
* we can't distinguish from OMS and NMS modules at glance, so try
|
|
* first using new module system
|
|
*/
|
|
factory = tc_new_module_factory(modpath, TC_MAX(verbose - 4, 0));
|
|
module = tc_new_module(factory, modtype, filename, TC_NONE);
|
|
|
|
if (module != NULL) {
|
|
const char *answer = NULL;
|
|
|
|
if (verbose >= TC_DEBUG) {
|
|
tc_log_info(EXE, "using new module system");
|
|
}
|
|
if (strlen(modcfg) > 0) {
|
|
int ret = tc_module_configure(module, modcfg, tc_get_vob());
|
|
if (ret == TC_OK) {
|
|
status = STATUS_OK;
|
|
} else {
|
|
status = STATUS_MODULE_FAILED;
|
|
tc_log_error(EXE, "configure returned error");
|
|
}
|
|
tc_module_stop(module);
|
|
} else {
|
|
if (verbose >= TC_INFO) {
|
|
/* overview and options */
|
|
tc_module_inspect(module, "help", &answer);
|
|
puts(answer);
|
|
/* module capabilities */
|
|
tc_module_show_info(module, verbose);
|
|
}
|
|
if (strlen(modarg) > 0) {
|
|
tc_log_info(EXE, "informations about '%s' for "
|
|
"module:", modarg);
|
|
tc_module_inspect(module, modarg, &answer);
|
|
puts(answer);
|
|
}
|
|
status = STATUS_OK;
|
|
}
|
|
tc_del_module(factory, module);
|
|
} else if (!strcmp(modtype, "filter"))
|
|
#endif /* ENABLE_EXPERIMENTAL */
|
|
{
|
|
char namebuf[NAME_LEN];
|
|
#ifdef ENABLE_EXPERIMENTAL
|
|
/* compatibility support only for filters */
|
|
if (verbose >= TC_DEBUG) {
|
|
tc_log_info(EXE, "using old module system");
|
|
}
|
|
#endif
|
|
/* ok, fallback to old module system */
|
|
strlcpy(namebuf, filename, NAME_LEN);
|
|
filter[0].name = namebuf;
|
|
|
|
ret = load_plugin(modpath, 0, verbose);
|
|
if (ret != 0) {
|
|
tc_log_error(__FILE__, "unable to load filter `%s' (path=%s)",
|
|
filter[0].name, modpath);
|
|
status = STATUS_NO_MODULE;
|
|
} else {
|
|
strlcpy(options, "help", OPTS_SIZE);
|
|
ptr.tag = TC_FILTER_INIT;
|
|
if ((ret = filter[0].entry(&ptr, options)) != 0) {
|
|
status = STATUS_MODULE_ERROR;
|
|
} else {
|
|
memset(options, 0, OPTS_SIZE);
|
|
ptr.tag = TC_FILTER_GET_CONFIG;
|
|
ret = filter[0].entry(&ptr, options);
|
|
|
|
if (ret == 0) {
|
|
if (verbose >= TC_INFO) {
|
|
fputs("START\n", stdout);
|
|
fputs(options, stdout);
|
|
fputs("END\n", stdout);
|
|
}
|
|
status = STATUS_OK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef ENABLE_EXPERIMENTAL
|
|
ret = tc_del_module_factory(factory);
|
|
#endif
|
|
tcv_free(tcv_handle);
|
|
return status;
|
|
}
|
|
|
|
/* just for correct linking purposes */
|
|
#ifdef ENABLE_EXPERIMENTAL
|
|
#include "libtc/tcframes.h"
|
|
void dummy_tcframes(void);
|
|
void dummy_tcframes(void) {
|
|
tc_del_video_frame(NULL);
|
|
tc_del_audio_frame(NULL);
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
/*************************************************************************/
|
|
|
|
/*
|
|
* Local variables:
|
|
* c-file-style: "stroustrup"
|
|
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*
|
|
* vim: expandtab shiftwidth=4:
|
|
*/
|