/* ** Copyright (C) 2003 Daniel Caujolle-Bert ** ** This program 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 of the License, or ** (at your option) any later version. ** ** This program 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 this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** * $Id: muxine.c,v 1.4 2005/09/12 00:47:03 miguelfreitas Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #ifndef VERSION #define VERSION "0.0.6" #endif typedef struct { Display *dpy; int screen; Window win; GLXContext ctx; XSetWindowAttributes attr; int x,y; unsigned int width, height; unsigned int bpp; }GLWindow; static xine_t *xine; static xine_stream_t *stream; static xine_video_port_t *vo_port; static xine_audio_port_t *ao_port; static xine_event_queue_t *event_queue; static Display *display; static int screen; static Window window; static int xpos, ypos, width, height; static double pixel_aspect; static int running = 0; static GLWindow GLWin; #define INPUT_MOTION (ExposureMask | ButtonPressMask | KeyPressMask | \ ButtonMotionMask | StructureNotifyMask | \ PropertyChangeMask | PointerMotionMask) static void dest_size_cb(void *data, int video_width, int video_height, double video_pixel_aspect, int *dest_width, int *dest_height, double *dest_pixel_aspect) { *dest_width = width; *dest_height = height; *dest_pixel_aspect = pixel_aspect; } static void frame_output_cb(void *data, int video_width, int video_height, double video_pixel_aspect, int *dest_x, int *dest_y, int *dest_width, int *dest_height, double *dest_pixel_aspect, int *win_x, int *win_y) { *dest_x = 0; *dest_y = 0; *win_x = xpos; *win_y = ypos; *dest_width = width; *dest_height = height; *dest_pixel_aspect = pixel_aspect; } static void event_listener(void *user_data, const xine_event_t *event) { switch(event->type) { case XINE_EVENT_UI_PLAYBACK_FINISHED: running = 0; break; } } /* taken from nehe´s glx_base */ void createGLWindow(const char* title, int width, int height, int bpp) { int attrListSgl[] = {GLX_RGBA, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16, None}; int attrListDbl[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16, None}; XVisualInfo *vi; Colormap cmap; int bestMode; Atom wmDelete; Window winDummy; unsigned int borderDummy; bestMode = 0; GLWin.dpy = XOpenDisplay(0); GLWin.screen = DefaultScreen(GLWin.dpy); vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl); if(NULL == vi) { vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListSgl); printf("Singlebuffered : true\n"); } else { printf("Doublebuffered : true\n"); } cmap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen),vi->visual, AllocNone); GLWin.attr.colormap = cmap; GLWin.attr.border_pixel = 0; GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask; GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr); wmDelete = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True); XSetWMProtocols(GLWin.dpy, GLWin.win, &wmDelete, 1); XSetStandardProperties(GLWin.dpy, GLWin.win, title, title, None, NULL, 0, NULL); XMapRaised(GLWin.dpy, GLWin.win); XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, &GLWin.width, &GLWin.height, &borderDummy, &GLWin.bpp); } int main(int argc, char **argv) { char configfile[2048]; x11_visual_t vis; double res_h, res_v; char *vo_driver = "opengl"; char *ao_driver = "auto"; char *mrl = NULL; int i; printf("muxine (xine µ player) v%s\n" "(c) 2003 by Daniel Caujolle-Bert .\n", VERSION); if(argc <= 1) { printf("specify one mrl\n"); return 0; } if(argc > 1) { for(i = 1; i < argc; i++) { if(!strcmp(argv[i], "-vo")) { vo_driver = argv[++i]; } else if(!strcmp(argv[i], "-ao")) { ao_driver = argv[++i]; } else if((!strcmp(argv[i], "-h")) || (!strcmp(argv[i], "--help"))) { printf("Options:\n"); printf(" -ao Audio output plugin name (default = alsa).\n"); printf(" -vo Video output plugin name (default = Xv).\n"); return 0; } else { mrl = argv[i]; } } } else mrl = argv[1]; if(!XInitThreads()) { printf("XInitThreads() failed\n"); return 0; } xine = xine_new(); sprintf(configfile, "%s%s", xine_get_homedir(), "/.xine/config"); xine_config_load(xine, configfile); xine_init(xine); //if((display = XOpenDisplay(getenv("DISPLAY"))) == NULL) { // printf("XOpenDisplay() failed.\n"); // return 0; //} createGLWindow("muxine accelerated", 640, 480, 24); screen = GLWin.screen; display = GLWin.dpy; window = GLWin.win; xpos = 0; ypos = 0; width = 320; height = 200; XLockDisplay(display); //window = XCreateSimpleWindow(display, XDefaultRootWindow(display), // xpos, ypos, width, height, 1, 0, 0); XSelectInput (display, window, INPUT_MOTION); //XMapRaised(display, window); res_h = (DisplayWidth(display, screen) * 1000 / DisplayWidthMM(display, screen)); res_v = (DisplayHeight(display, screen) * 1000 / DisplayHeightMM(display, screen)); XSync(display, False); XUnlockDisplay(display); vis.display = display; vis.screen = screen; vis.d = window; vis.dest_size_cb = dest_size_cb; vis.frame_output_cb = frame_output_cb; vis.user_data = NULL; pixel_aspect = res_v / res_h; if(fabs(pixel_aspect - 1.0) < 0.01) pixel_aspect = 1.0; if((vo_port = xine_open_video_driver(xine, vo_driver, XINE_VISUAL_TYPE_X11, (void *) &vis)) == NULL) { printf("I'm unable to initialize '%s' video driver. Giving up.\n", vo_driver); return 0; } ao_port = xine_open_audio_driver(xine , ao_driver, NULL); stream = xine_stream_new(xine, ao_port, vo_port); event_queue = xine_event_new_queue(stream); xine_event_create_listener_thread(event_queue, event_listener, NULL); xine_gui_send_vo_data(stream, XINE_GUI_SEND_DRAWABLE_CHANGED, (void *) window); xine_gui_send_vo_data(stream, XINE_GUI_SEND_VIDEOWIN_VISIBLE, (void *) 1); if((!xine_open(stream, mrl)) || (!xine_play(stream, 0, 0))) { printf("Unable to open mrl '%s'\n", mrl); return 0; } running = 1; while(running) { XEvent xevent; int got_event; XLockDisplay(display); got_event = XPending(display); if( got_event ) XNextEvent(display, &xevent); XUnlockDisplay(display); if( !got_event ) { xine_usec_sleep(20000); continue; } switch(xevent.type) { case Expose: if(xevent.xexpose.count != 0) break; xine_gui_send_vo_data(stream, XINE_GUI_SEND_EXPOSE_EVENT, &xevent); break; case ConfigureNotify: { XConfigureEvent *cev = (XConfigureEvent *) &xevent; Window tmp_win; width = cev->width; height = cev->height; if((cev->x == 0) && (cev->y == 0)) { XLockDisplay(display); XTranslateCoordinates(display, cev->window, DefaultRootWindow(cev->display), 0, 0, &xpos, &ypos, &tmp_win); XUnlockDisplay(display); } else { xpos = cev->x; ypos = cev->y; } } break; } } xine_close(stream); xine_event_dispose_queue(event_queue); xine_dispose(stream); if(ao_port) xine_close_audio_driver(xine, ao_port); xine_close_video_driver(xine, vo_port); xine_exit(xine); XLockDisplay(display); XUnmapWindow(display, window); XDestroyWindow(display, window); XUnlockDisplay(display); XCloseDisplay (display); return 1; } /* * Local variables: * compile-command: "gcc -Wall -O2 `xine-config --cflags` `xine-config --libs` -I/usr/X11R6/include -L/usr/X11R6/lib -lX11 -lGl -lm -o muxine muxine.c" * End: */