続々 xine
#include <sys/param.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/keysym.h> #include <X11/extensions/XShm.h> #include <xine.h> #include <xine/xineutils.h> #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 struct wininfo { int x, y; int width, height; double aspect; }; static int running = 0; static void dest_size_cb(void *user_data, int video_width, int video_height, double video_pixel_aspect, int *dest_width, int *dest_height, double *dest_pixel_aspect) { struct wininfo *wi = (struct wininfo *)user_data; (void)video_width; (void)video_height; (void)video_pixel_aspect; *dest_width = wi->width; *dest_height = wi->height; *dest_pixel_aspect = wi->aspect; } static void frame_output_cb(void *user_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) { struct wininfo *wi = (struct wininfo *)user_data; (void)video_width; (void)video_height; (void)video_pixel_aspect; *dest_x = 0; *dest_y = 0; *win_x = wi->x; *win_y = wi->y; *dest_width = wi->width; *dest_height = wi->height; *dest_pixel_aspect = wi->aspect; } static void xine_event_handler(void *user_data, const xine_event_t *event) { (void)user_data; switch (event->type) { case XINE_EVENT_UI_PLAYBACK_FINISHED: running = 0; break; } } static char *progname; static void usage(void) { fprintf(stderr, "Usage: %s [filename]\n", progname); exit(1); } int main(int argc, char *argv[]) { /* xine */ xine_t *xine; xine_video_port_t *video_port; xine_audio_port_t *audio_port; xine_stream_t *stream; xine_event_queue_t *evqueue; x11_visual_t visual; char config_path[MAXPATHLEN]; /* X11 */ Display *display; int screen; Window window, root_window, child_window; Atom proto, delwin; XEvent ev; KeySym ksym; XWindowAttributes attr; XSizeHints size; unsigned int width, height, border, depth; int x, y; int shmcomptype; /* misc */ struct stat sb; struct wininfo wininfo; progname = argv[0]; if ((argc < 2) || (stat(argv[1], &sb) < 0) || !S_ISREG(sb.st_mode)) { usage(); } XInitThreads(); display = XOpenDisplay(NULL); if (display == NULL) { fprintf(stderr, "Error: Can't open display\n"); exit(1); } screen = DefaultScreen(display); window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, WhitePixel(display, screen), BlackPixel(display, screen)); size.flags = PMinSize | PMaxSize; size.min_width = SCREEN_WIDTH; size.min_height = SCREEN_HEIGHT; size.max_width = SCREEN_WIDTH; size.max_height = SCREEN_HEIGHT; XSetNormalHints(display, window, &size); XStoreName(display, window, argv[1]); proto = XInternAtom(display, "WM_PROTOCOLS", 0); delwin = XInternAtom(display, "WM_DELETE_WINDOW", 0); XSetWMProtocols(display, window, &delwin, 1); XSelectInput(display, window, KeyPressMask|ButtonPressMask|ExposureMask|StructureNotifyMask); if (XShmQueryExtension(display)) shmcomptype = XShmGetEventBase(display) + ShmCompletion; else shmcomptype = -1; XMapRaised(display, window); XSync(display, False); XGetGeometry(display, window, &root_window, &x, &y, &width, &height, &border, &depth); XGetWindowAttributes(display, window, &attr); XTranslateCoordinates(display, window, attr.root, 0, 0, &x, &y, &child_window); memset(&visual, 0, sizeof(visual)); visual.display = display; visual.screen = screen; visual.d = window; visual.dest_size_cb = dest_size_cb; visual.frame_output_cb = frame_output_cb; visual.user_data = &wininfo; wininfo.x = x; wininfo.y = y; wininfo.width = width; wininfo.height = height; wininfo.aspect = 1.0; /* XXX */ xine = xine_new(); snprintf(config_path, sizeof(config_path), "%s/.xine/config", xine_get_homedir()); xine_config_load(xine, config_path); xine_init(xine); video_port = xine_open_video_driver(xine, NULL, XINE_VISUAL_TYPE_X11, &visual); audio_port = xine_open_audio_driver(xine, NULL, NULL); stream = xine_stream_new(xine, audio_port, video_port); evqueue = xine_event_new_queue(stream); xine_event_create_listener_thread(evqueue, xine_event_handler, NULL); xine_port_send_gui_data(video_port, XINE_GUI_SEND_DRAWABLE_CHANGED, (void *)window); xine_port_send_gui_data(video_port, XINE_GUI_SEND_VIDEOWIN_VISIBLE, (void *)1); running = 1; if (!xine_open(stream, argv[1]) || (!xine_play(stream, 0, 0))) running = 0; while (running) { if (XPending(display) > 0) { XNextEvent(display, &ev); switch (ev.type) { case Expose: if ((ev.xexpose.count == 0) && (ev.xexpose.window == window)) { xine_gui_send_vo_data(stream, XINE_GUI_SEND_EXPOSE_EVENT, &ev); } break; case KeyPress: ksym = XLookupKeysym(&ev.xkey, 0); switch (ksym) { case XK_q: case XK_Q: case XK_space: case XK_Escape: case XK_Return: case XK_KP_Enter: running = 0; break; } break; case ButtonPress: switch (ev.xbutton.button) { case 1: case 2: case 3: running = 0; break; } break; case ConfigureNotify: if ((ev.xconfigure.x == 0) && (ev.xconfigure.y == 0)) { XLockDisplay(display); XGetWindowAttributes(display, ev.xconfigure.window, &attr); XTranslateCoordinates(display, ev.xconfigure.window, attr.root, 0, 0, &x, &y, &child_window); XUnlockDisplay(display); wininfo.x = x; wininfo.y = y; } else { wininfo.x = ev.xconfigure.x; wininfo.y = ev.xconfigure.y; } wininfo.width = ev.xconfigure.width; wininfo.height = ev.xconfigure.height; break; case ClientMessage: if ((ev.xclient.message_type == proto) && ((Atom)ev.xclient.data.l[0] == delwin)) { running = 0; } break; default: if (ev.type == shmcomptype) { xine_gui_send_vo_data(stream, XINE_GUI_SEND_COMPLETION_EVENT, &ev); } break; } } else { usleep(1); } } xine_close(stream); xine_event_dispose_queue(evqueue); xine_dispose(stream); xine_close_audio_driver(xine, audio_port); xine_close_video_driver(xine, video_port); xine_exit(xine); XUnmapWindow(display, window); XDestroyWindow(display, window); XCloseDisplay(display); return 0; }