summaryrefslogtreecommitdiff
path: root/xine_frontend_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'xine_frontend_main.c')
-rw-r--r--xine_frontend_main.c379
1 files changed, 379 insertions, 0 deletions
diff --git a/xine_frontend_main.c b/xine_frontend_main.c
new file mode 100644
index 00000000..48c13971
--- /dev/null
+++ b/xine_frontend_main.c
@@ -0,0 +1,379 @@
+/*
+ * Simple main() routine for stand-alone frontends.
+ *
+ * See the main source file 'xineliboutput.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id: xine_frontend_main.c,v 1.1 2006-06-03 10:01:18 phintuka Exp $
+ *
+ */
+
+#include <termios.h>
+#include <unistd.h>
+
+#if 0
+static void xine_log_cb(void *data, int section)
+{
+ fprintf(stderr, "xine: log section %d\n",section);
+}
+
+static void print_xine_log(xine_t *xine)
+{
+ int i, j;
+ int logs = xine_get_log_section_count(xine);
+ const char * const * names = xine_get_log_names(xine);
+ for(i=0; i<logs; i++) {
+ const char * const * lines = xine_get_log(xine, i);
+ if(lines[0]) {
+ printf("\nLOG: %s\n",names[i]);
+ j=-1;
+ while(lines[++j] && *lines[++j] )
+ printf(" %2d: %s", j, lines[j]);
+ }
+ }
+}
+#endif
+
+/* static data */
+pthread_t kbd_thread;
+struct termios tm, saved_tm;
+volatile int terminate_key_pressed = 0;
+
+void *kbd_receiver_thread(void *fe)
+{
+ struct pollfd pfd;
+ char ch;
+ int err;
+
+ terminate_key_pressed = 0;
+
+ /* Set stdin to deliver keypresses without buffering whole lines */
+ tcgetattr(STDIN_FILENO, &saved_tm);
+ if (tcgetattr(STDIN_FILENO, &tm) == 0) {
+ tm.c_iflag = 0;
+ tm.c_lflag &= ~(ICANON | ECHO);
+ tm.c_cc[VMIN] = 0;
+ tm.c_cc[VTIME] = 0;
+ tcsetattr(STDIN_FILENO, TCSANOW, &tm);
+ }
+
+ do {
+ errno = 0;
+ pfd.fd = STDIN_FILENO;
+ pfd.events = POLLIN;
+ err = poll(&pfd, 1, 250);
+ if(err==1) {
+ if(1 == read(STDIN_FILENO, &ch, 1)) {
+ /* forward keyboard input to server */
+ uint64_t code = ch;
+ char str[64];
+ while(poll(&pfd,1,0) == 1 && read(STDIN_FILENO,&ch,1) == 1)
+ code = (code<<8) | (ch & 0xff);
+
+ if(code == 27) { //ch == 'q' || ch == 'Q' /*|| ch == 27*/) {
+ terminate_key_pressed = 1;
+ break;
+ } //else {
+
+ snprintf(str, sizeof(str), "%016LX", code);
+ if(find_input((fe_t*)fe))
+ process_xine_keypress(((fe_t*)fe)->input, "KBD", str, 0, 0);
+ }
+ }
+
+ } while(err >= 0 || errno == EINTR);
+
+ LOGMSG("Keyboard thread terminated");
+ tcsetattr(STDIN_FILENO, TCSANOW, &saved_tm);
+ pthread_exit(NULL);
+ return NULL; /* never reached */
+}
+
+static char *strcatrealloc(char *dest, const char *src)
+{
+ int l;
+
+ if (!src || !*src)
+ return dest;
+
+ l = (dest ? strlen(dest) : 0) + strlen(src) + 1;
+ if(dest) {
+ dest = (char *)realloc(dest, l);
+ strcat(dest, src);
+ } else {
+ dest = (char*)malloc(l);
+ strcpy(dest, src);
+ }
+ return dest;
+}
+
+int main(int argc, char *argv[])
+{
+ char *mrl = NULL, *gdrv = NULL, *adrv = NULL, *adev = NULL;
+ int ftcp = 0, fudp = 0, frtp = 0;
+ int fullscreen = 0, width = 720, height = 576;
+ int scale_video = 1, aspect = 1;
+ char *video_port = NULL;
+ int xmajor, xminor, xsub;
+ int i, err;
+ frontend_t *fe = NULL;
+ extern const fe_creator_f fe_creator;
+ char *static_post_plugins = NULL;
+ void *p;
+ char *exec_name = argv[0];
+
+ if(strrchr(argv[0],'/'))
+ exec_name = strrchr(argv[0],'/')+1;
+
+ xine_get_version(&xmajor, &xminor, &xsub);
+ printf("%s %s (build with xine-lib %d.%d.%d, using xine-lib %d.%d.%d)\n\n",
+ exec_name,
+ FE_VERSION_STR,
+ XINE_MAJOR_VERSION, XINE_MINOR_VERSION, XINE_SUB_VERSION,
+ xmajor, xminor, xsub);
+
+ /* Parse arguments */
+ for(i=1; i<argc; i++) {
+ if(!strncmp(argv[i], "--help", 6)) {
+ printf("\n"
+ "Usage: %s [options] [xvdr:[udp:|tcp:|rtp:]//host:port] \n"
+ "\n"
+ "Available options:\n"
+ " --help \n"
+ " --fullscreen \n"
+ " --width x \n"
+ " --height x \n"
+ " --lirc [devicename] \n"
+ " --audio audiodriver[:device] \n"
+ " --video videodriver \n",
+ exec_name);
+ printf(" --display displayaddress \n"
+ " --verbose \n"
+ " --silent \n"
+ " --syslog \n"
+ " --tcp \n"
+ " --udp \n"
+ " --rtp \n"
+ " --aspect [auto|4:3|16:9|default] \n"
+ " --noscaling \n"
+ " --post name[:arg=val[,arg=val]]\n");
+ exit(0);
+ } else if(!strncmp(argv[i], "--fullscreen", 12)) {
+ fullscreen=1;
+ printf("Fullscreen mode\n");
+ } else if(!strncmp(argv[i], "--verbose", 9)) {
+ verbose_xine_log = 1;
+ SysLogLevel = 3;
+ printf("Verbose mode\n");
+ } else if(!strncmp(argv[i], "--silent", 8)) {
+ verbose_xine_log = 0;
+ SysLogLevel = 1;
+ printf("Silent mode\n");
+ } else if(!strncmp(argv[i], "--noscaling", 11)) {
+ scale_video = 0;
+ printf("Video scaling disabled\n");
+ } else if(!strncmp(argv[i], "--tcp", 5)) {
+ ftcp = 1;
+ printf("Protocol: TCP\n");
+ } else if(!strncmp(argv[i], "--udp", 5)) {
+ fudp = 1;
+ printf("Protocol: UDP\n");
+ } else if(!strncmp(argv[i], "--rtp", 5)) {
+ frtp = 1;
+ printf("Protocol: RTP\n");
+ } else if(!strncmp(argv[i], "--syslog", 8)) {
+ LogToSysLog = 1;
+ openlog(exec_name, LOG_PID|LOG_CONS, LOG_USER);
+ } else if(!strncmp(argv[i], "--video", 7)) {
+ if(argc > ++i) {
+ gdrv = strdup(argv[i]);
+ printf("Video driver: %s\n",gdrv);
+ }
+ } else if(!strncmp(argv[i], "--audio", 7)) {
+ if(argc > ++i) {
+ adrv = strdup(argv[i]);
+ adev = strchr(adrv, ':');
+ if(adev)
+ *(adev++) = 0;
+ printf("Audio driver: %s\n",adrv);
+ if(adev)
+ printf("Audio device: %s\n",adev);
+ }
+ } else if(!strncmp(argv[i], "--post", 6)) {
+ if(argc > ++i) {
+ if(static_post_plugins)
+ strcatrealloc(static_post_plugins, ";");
+ static_post_plugins = strcatrealloc(static_post_plugins, argv[i]);
+ printf("Post plugins: %s\n", static_post_plugins);
+ }
+ } else if(!strncmp(argv[i], "--height", 8)) {
+ if(argc > ++i) height = atoi(argv[i]);
+ printf("Height: %d\n", height);
+ } else if(!strncmp(argv[i], "--aspect", 8)) {
+ if(argc > ++i) {
+ if(!strncmp(argv[i], "auto", 4))
+ aspect = 0;
+ if(!strncmp(argv[i], "4:3", 3))
+ aspect = 2;
+ if(!strncmp(argv[i], "16:9", 4))
+ aspect = 3;
+ printf("Aspect ratio: %s\n",
+ aspect==0?"Auto":aspect==2?"4:3":aspect==3?"16:9":"Default");
+ }
+ } else if(!strncmp(argv[i], "--display", 9)) {
+ if(argc > ++i) video_port = strdup(argv[i]);
+ } else if(!strncmp(argv[i], "--width", 7)) {
+ if(argc > ++i) width = atoi(argv[i]);
+ } else if(!strncmp(argv[i], "--lirc", 6)) {
+ if(argc > i+1 && argv[i+1][0] == '/')
+ lirc_device_name = strdup(argv[++i]);
+ else
+ lirc_device_name = strdup("/dev/lircd");
+ printf("LIRC device: %s\n", lirc_device_name);
+ } else {
+ if(argv[i][0] != '-') {
+ mrl = strdup(argv[i]);
+ printf("VDR Server: %s\n", mrl);
+ } else {
+ fprintf(stderr, "Unknown argument: %s\n", argv[i]);
+ exit(-1);
+ }
+ }
+ }
+ printf("\n");
+
+ /* check xine-lib version */
+ if(!xine_check_version(1, 1, 0)) {
+ fprintf(stderr,"ERROR: xine-lib is too old, require at least "
+ "xine library version 1.1.0\n");
+ return 1;
+ }
+
+ /* If server address not given, try to find server automatically */
+ if(!mrl ||
+ !strcmp(mrl, "xvdr:") ||
+ !strcmp(mrl, "xvdr:tcp:") ||
+ !strcmp(mrl, "xvdr:udp:") ||
+ !strcmp(mrl, "xvdr:rtp:") ||
+ !strcmp(mrl, "xvdr:pipe:")) {
+ char address[1024] = "";
+ int port = -1;
+ printf("VDR server not given, searching ...\n");
+ if(search_vdr_server(&port, &address[0])) {
+ printf("Found VDR server: host %s, port %d\n", address, port);
+ if(mrl) {
+ char *tmp = mrl;
+ mrl = NULL;
+ asprintf(&mrl, "%s//%s:%d", tmp, address, port);
+ free(tmp);
+ } else
+ asprintf(&mrl, "xvdr://%s:%d", address, port);
+ } else {
+ printf("WARNING:\n"
+ " MRL not given and server not found from local network.\n"
+ " Trying to connect to default port on local host.\n");
+ mrl = strdup("xvdr://127.0.0.1");
+ }
+ }
+
+ {
+ char *tmp = NULL, *mrl2 = mrl;
+ if(frtp && !strstr(mrl, "rtp:"))
+ tmp = strdup("xvdr:rtp:");
+ else if(fudp && !strstr(mrl, "udp:"))
+ tmp = strdup("xvdr:udp:");
+ else if(ftcp && !strstr(mrl, "tcp:"))
+ tmp = strdup("xvdr:tcp:");
+ if(tmp) {
+ mrl = strcatrealloc(tmp, strchr(mrl, '/'));
+ free(mrl2);
+ }
+ }
+
+ /* Create front-end */
+ fe = (*fe_creator)();
+ if(!fe) {
+ printf("Error initializing frontend\n");
+ return 3;
+ }
+
+ /* Initialize display */
+ if(!fe->fe_display_open(fe, width, height, fullscreen, 0,
+ "", aspect, NULL, video_port, scale_video, 0)) {
+ printf("Error opening display\n");
+ fe->fe_free(fe);
+ return 4;
+ }
+
+ /* Initialize xine */
+ if(!fe->xine_init(fe, adrv, adev, gdrv, 250, 1, static_post_plugins)) {
+ printf("Error initializing xine\n");
+ fe->fe_free(fe);
+ return 5;
+ }
+
+ /* Connect to VDR xineliboutput server */
+ if(!fe_xine_open(fe, mrl)) {
+ /*print_xine_log(((fe_t *)fe)->xine);*/
+ printf("Error opening %s\n", mrl);
+ fe->fe_free(fe);
+ return 6;
+ }
+
+ printf("\n\nPress Esc to exit\n\n");
+
+ if(!fe->xine_play(fe)) {
+ /*print_xine_log(((fe_t *)fe)->xine);*/
+ /*printf("Error playing %s//%s:%s\n", argv[1], host, port);*/
+ printf("Error playing %s\n", argv[1]);
+ fe->fe_free(fe);
+ return 7;
+ }
+
+ /* Start LIRC forwarding */
+ if(lirc_device_name) {
+ if ((err = pthread_create (&lirc_thread,
+ NULL, lirc_receiver_thread,
+ (void*)fe)) != 0) {
+ fprintf(stderr, "can't create new thread for lirc (%s)\n",
+ strerror(err));
+ }
+ }
+
+ /* Start keyboard listener thread */
+ if ((err = pthread_create (&kbd_thread,
+ NULL, kbd_receiver_thread,
+ (void*)fe)) != 0) {
+ fprintf(stderr, "can't create new thread for lirc (%s)\n",
+ strerror(err));
+ }
+
+ /* Main loop */
+
+ sleep(2); /* give input_vdr some time to establish connection */
+
+ while(fe->fe_run(fe) && !fe->xine_is_finished(fe) && !terminate_key_pressed)
+ pthread_yield();
+
+ /* Clean up */
+
+ printf("Terminating...\n");
+
+ if(lirc_device_name) {
+ /*free(lirc_device_name);*/
+ lirc_device_name = NULL;
+ if(fd_lirc >= 0)
+ close(fd_lirc);
+ fd_lirc = -1;
+ pthread_cancel (lirc_thread);
+ pthread_join (lirc_thread, &p);
+ }
+
+ pthread_cancel (kbd_thread);
+ pthread_join (kbd_thread, &p);
+
+ tcsetattr(STDIN_FILENO, TCSANOW, &saved_tm);
+
+ fe->fe_free(fe);
+ return 0;
+}