rendered paste body/*
** Copyright (C) 2003 Daniel Caujolle-Bert <segfault@club-internet.fr>
**
** 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 <stdio.h>
#include <string.h>
#include <math.h>
#include <sys/time.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/glx.h>
#include <GL/gl.h>
#include <xine.h>
#include <xine/xineutils.h>
#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;
}
}
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 <f1rmb@users.sourceforge.net>.\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 <ao name> Audio output plugin name (default = alsa).\n");
printf(" -vo <vo name> 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:
*/