File indexing completed on 2024-04-21 15:38:31

0001 /* This file is part of the KMPlayer application
0002    Copyright (C) 2004 Koos Vriezen <koos.vriezen@xs4all.nl>
0003 
0004    This program is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This program is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012     General Public License for more details.
0013 
0014    You should have received a copy of the GNU General Public License
0015    along with this program; see the file COPYING.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include <stdio.h>
0021 #include <string.h>
0022 #include <math.h>
0023 #include "config-kmplayer.h"
0024 #include <dcopclient.h>
0025 #include <qcstring.h>
0026 #include <qtimer.h>
0027 #include <qfile.h>
0028 #include <qurl.h>
0029 #include <qthread.h>
0030 #include <qmutex.h>
0031 #include <qdom.h>
0032 #include "kmplayer_backend.h"
0033 #include "kmplayer_callback_stub.h"
0034 #include "kmplayer_callback.h"
0035 #include "xvplayer.h"
0036 #include <X11/X.h>
0037 #include <X11/Xlib.h>
0038 #include <X11/Xutil.h>
0039 #include <X11/keysym.h>
0040 #include <X11/Xatom.h>
0041 #include <X11/Xutil.h>
0042 #include <X11/extensions/XShm.h>
0043 #include <X11/extensions/Xvlib.h>
0044 
0045 
0046 static char                 configfile[2048];
0047 
0048 static Display             *display;
0049 static KXVideoPlayer       *xvapp;
0050 static KMPlayer::Callback_stub * callback;
0051 static Window               wid;
0052 static GC                   gc;
0053 static bool                 window_created = true;
0054 static bool                 wants_config;
0055 static bool                 verbose;
0056 static bool                 running;
0057 static bool                 have_freq;
0058 static bool                 xv_success;
0059 static bool                 reset_xv_autopaint_colorkey;
0060 static bool                 reset_xv_mute;
0061 static int                  xvport;
0062 static int                  xv_encoding = -1;
0063 static QString              xv_norm;
0064 static int                  xv_frequency;
0065 static int                  screen;
0066 static int                  movie_width;
0067 static int                  movie_height;
0068 static int                  current_volume;
0069 static int                  tmp_volume;
0070 static const int            start_vol_timeout = 100;
0071 static const int            inc_vol_timeout = 20;
0072 Atom xv_enc_atom;
0073 Atom xv_hue_atom;
0074 Atom xv_saturation_atom;
0075 Atom xv_brightness_atom;
0076 Atom xv_contrast_atom;
0077 Atom xv_freq_atom;
0078 Atom xv_volume_atom;
0079 Atom xv_mute_atom;
0080 Atom xv_autopaint_colorkey_atom;
0081 enum {
0082     limit_volume = 0,
0083     limit_hue, limit_contrast, limit_brightness, limit_saturation,
0084     limit_last
0085 };
0086 static struct Limit { int min; int max; } xv_limits [limit_last];
0087 static QString elmentry ("entry");
0088 static QString elmitem ("item");
0089 static QString attname ("name");
0090 static QString atttype ("type");
0091 static QString attdefault ("DEFAULT");
0092 static QString attvalue ("value");
0093 //static QString attstart ("START");
0094 //static QString attend ("END");
0095 //static QString valrange ("range");
0096 //static QString valnum ("num");
0097 //static QString valbool ("bool");
0098 //static QString valenum ("enum");
0099 //static QString valstring ("string");
0100 static QString valtree ("tree");
0101 static QByteArray config_buf;
0102 
0103 extern "C" {
0104 
0105 } // extern "C"
0106 
0107 static void putVideo () {
0108     XWindowAttributes attr;
0109     XGetWindowAttributes (display, wid, &attr);
0110     XvPutVideo (display, xvport, wid, gc, 0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height);
0111 }
0112 
0113 using namespace KMPlayer;
0114 
0115 Backend::Backend ()
0116     : DCOPObject (QCString ("Backend")) {
0117 }
0118 
0119 Backend::~Backend () {}
0120 
0121 void Backend::setURL (unsigned long, QString) {
0122 }
0123 
0124 void Backend::setSubTitleURL (unsigned long, QString) {
0125 }
0126 
0127 void Backend::play (long unsigned int, int) {
0128     xvapp->play ();
0129 }
0130 
0131 void Backend::stop (unsigned long) {
0132     QTimer::singleShot (0, xvapp, SLOT (stop ()));
0133 }
0134 
0135 void Backend::pause (unsigned long) {
0136 }
0137 
0138 void Backend::seek (unsigned long, int, bool /*absolute*/) {
0139 }
0140 
0141 void Backend::hue (unsigned long, int h, bool) {
0142     if (xv_limits[limit_hue].max > xv_limits[limit_hue].min)
0143         xvapp->hue ((h + 100) * (xv_limits[limit_hue].max - xv_limits[limit_hue].min)/200 + xv_limits[limit_hue].min);
0144 }
0145 
0146 void Backend::saturation (unsigned long, int s, bool) {
0147     if (xv_limits[limit_saturation].max > xv_limits[limit_saturation].min)
0148         xvapp->saturation ((s + 100) * (xv_limits[limit_saturation].max - xv_limits[limit_saturation].min)/200 + xv_limits[limit_saturation].min);
0149 }
0150 
0151 void Backend::contrast (unsigned long, int c, bool) {
0152     if (xv_limits[limit_contrast].max > xv_limits[limit_contrast].min)
0153         xvapp->contrast ((c + 100)*(xv_limits[limit_contrast].max - xv_limits[limit_contrast].min)/200 + xv_limits[limit_contrast].min);
0154 }
0155 
0156 void Backend::brightness (unsigned long, int b, bool) {
0157     if (xv_limits[limit_brightness].max > xv_limits[limit_brightness].min)
0158         xvapp->brightness ((b + 100)*(xv_limits[limit_brightness].max - xv_limits[limit_brightness].min)/200 + xv_limits[limit_brightness].min);
0159 }
0160 
0161 void Backend::volume (unsigned long, int v, bool) {
0162     if (xv_limits[limit_volume].max > xv_limits[limit_volume].min)
0163         xvapp->volume (v*(xv_limits[limit_volume].max - xv_limits[limit_volume].min)/100 + xv_limits[limit_volume].min);
0164 }
0165 
0166 void Backend::property (unsigned long wid, QString prop, QString val) {
0167     if (prop == "frequency")
0168         xvapp->frequency (val.toInt ());
0169 }
0170 
0171 void Backend::setAudioLang (unsigned long, int, QString) {
0172 }
0173 
0174 void Backend::setSubtitle (unsigned long, int, QString) {
0175 }
0176 
0177 void Backend::quit () {
0178     delete callback;
0179     callback = 0L;
0180     if (running)
0181         stop (0);
0182     else
0183         QTimer::singleShot (0, qApp, SLOT (quit ()));
0184 }
0185 
0186 bool updateConfigEntry (const QString & name, const QString & value) {
0187     fprintf (stderr, "%s=%s\n", name.ascii (), (const char *) value.local8Bit ());
0188     return true;
0189 }
0190 
0191 void Backend::setConfig (QByteArray data) {
0192     QString err;
0193     int line, column;
0194     QDomDocument dom;
0195     if (dom.setContent (data, false, &err, &line, &column)) {
0196         if (dom.childNodes().length () == 1) {
0197             for (QDomNode node = dom.firstChild().firstChild();
0198                     !node.isNull ();
0199                     node = node.nextSibling ()) {
0200                 QDomNamedNodeMap attr = node.attributes ();
0201                 updateConfigEntry (attr.namedItem (attname).nodeValue (),
0202                                    attr.namedItem (attvalue).nodeValue ());
0203             }
0204         } else
0205             err = QString ("invalid data");
0206     }
0207     if (callback)
0208         callback->errorMessage (0, 0, err);
0209 }
0210 
0211 bool Backend::isPlaying (unsigned long) {
0212     return running;
0213 }
0214 
0215 KXVideoPlayer::KXVideoPlayer (int _argc, char ** _argv)
0216   : QApplication (_argc, _argv, false), mute_timer (0) {
0217 }
0218 
0219 void KXVideoPlayer::init () {
0220     int xpos    = 0;
0221     int ypos    = 0;
0222     int width   = 320;
0223     int height  = 200;
0224 
0225     XLockDisplay(display);
0226     if (window_created)
0227         wid = XCreateSimpleWindow(display, XDefaultRootWindow(display),
0228                 xpos, ypos, width, height, 1, 0, 0);
0229     if (!callback)
0230         QTimer::singleShot (10, this, SLOT (play ()));
0231     XSelectInput (display, wid,
0232                   (PointerMotionMask | ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask)); // | SubstructureNotifyMask));
0233     XvAdaptorInfo * ai;
0234     unsigned int adaptors;
0235     xv_success = true;
0236     QDomDocument doc;
0237     QDomElement root = doc.createElement (QString ("document"));
0238     if (XvQueryAdaptors (display, XDefaultRootWindow (display), &adaptors, &ai) == Success) {
0239         QDomElement elm = doc.createElement (elmentry);
0240         elm.setAttribute (attname, QString ("XVideo"));
0241         elm.setAttribute (atttype, valtree);
0242         for (unsigned i = 0; i < adaptors; i++) {
0243             if ((ai[i].type & XvInputMask) &&
0244                     (ai[i].type & XvVideoMask) &&
0245                     ai[i].base_id > 0) {
0246                 int port = ai[i].base_id;
0247                 fprintf (stderr, "xvport %d\n", port);
0248                 bool freq_found = false;
0249                 XvAttribute *attributes = 0L;
0250                 int nr_attr, cur_val;
0251                 attributes = XvQueryPortAttributes (display, port, &nr_attr);
0252                 if (attributes) {
0253                     for (int i = 0; i < nr_attr; i++) {
0254                         if (!strcmp (attributes[i].name, "XV_FREQ"))
0255                             freq_found = true;
0256                         Atom atom = XInternAtom (display, attributes[i].name, false);
0257                         fprintf (stderr, "%s[%d] (%d .. %d)", attributes[i].name, ( int ) atom, attributes[i].min_value, attributes[i].max_value);
0258                         if ((attributes[i].flags & XvGettable) && XvGetPortAttribute (display, port, atom, &cur_val) == Success)
0259                             fprintf (stderr, " current: %d", cur_val);
0260                         fprintf (stderr, "\n");
0261                     }
0262                     XFree(attributes);
0263                 }
0264                 if (!xvport && ((xv_frequency > 0) == freq_found)) {
0265                     fprintf (stderr, "using xvport %d\n", port);
0266                     xvport = port;
0267                 }
0268                 if (xvport == port)
0269                     have_freq = freq_found;
0270                 XvEncodingInfo * encodings = 0L;
0271                 unsigned nr_encode;
0272                 XvQueryEncodings (display, port, &nr_encode, &encodings);
0273                 if (encodings) {
0274                     QDomElement port_item = doc.createElement (QString("Port"));
0275                     port_item.setAttribute (attvalue, QString::number (port));
0276                     if (freq_found)
0277                         port_item.setAttribute (QString("FREQ"), QString("1"));
0278                     for (unsigned i = 0; i < nr_encode; i++) {
0279                         if (strcmp (encodings[i].name, "XV_IMAGE")) {
0280                             if (xvport == port && xv_encoding < 0 && !xv_norm.isEmpty () && QString (encodings[i].name).lower ().startsWith(xv_norm.lower ()))
0281                                 xv_encoding = encodings[i].encoding_id;
0282                             if (port == xvport && encodings[i].encoding_id == xv_encoding) {
0283                                 movie_width = encodings[i].width;
0284                                 movie_height = encodings[i].height;
0285                             }
0286                             QDomElement item = doc.createElement (QString ("Input"));
0287                             item.setAttribute (attvalue, QString::number (encodings[i].encoding_id));
0288                             item.setAttribute (attname, QString (encodings[i].name));
0289                             port_item.appendChild (item);
0290                             fprintf (stderr, " encoding: %d %s\n", ( int ) encodings[i].encoding_id, encodings[i].name);
0291                         }
0292                     }
0293                     elm.appendChild (port_item);
0294                     XvFreeEncodingInfo (encodings);
0295                 }
0296             }
0297         }
0298         root.appendChild (elm);
0299         XvFreeAdaptorInfo(ai);
0300     }
0301     doc.appendChild (root);
0302     QCString exp = doc.toCString ();
0303     config_buf = exp;
0304     //fprintf (stderr, "%s\n", (const char *)exp);
0305     config_buf.resize (exp.length ()); // strip terminating \0
0306 
0307     if (xvport <= 0) {
0308         fprintf (stderr, "no valid xvport found\n");
0309         xv_success = false;
0310         return;
0311     }
0312     if (window_created) {
0313         fprintf (stderr, "map %lu\n", wid);
0314         if (movie_width > 0 && movie_height > 0)
0315             XResizeWindow (display, wid, movie_width, movie_height);
0316         XMapRaised(display, wid);
0317         XSync(display, False);
0318     }
0319     XUnlockDisplay(display);
0320     if (!xv_success)
0321         fprintf (stderr, "Failed to init %d port\n", xvport);
0322 }
0323 
0324 KXVideoPlayer::~KXVideoPlayer () {
0325     if (window_created) {
0326         XLockDisplay (display);
0327         fprintf (stderr, "unmap %lu\n", wid);
0328         XUnmapWindow (display,  wid);
0329         XDestroyWindow(display,  wid);
0330         XSync (display, False);
0331         XUnlockDisplay (display);
0332     }
0333     xvapp = 0L;
0334 }
0335 
0336 void getConfigEntries (QByteArray & buf) {
0337     QDomDocument doc;
0338     QDomElement root = doc.createElement (QString ("document"));
0339     doc.appendChild (root);
0340     QCString exp = doc.toCString ();
0341     buf = exp;
0342     buf.resize (exp.length ()); // strip terminating \0
0343 }
0344 
0345 void KXVideoPlayer::play () {
0346     fprintf (stderr, "play xv://%d:%d/%d\n", xvport, xv_encoding, xv_frequency);
0347     if (!xv_success)
0348         return;
0349     if (callback && movie_width > 0 && movie_height > 0)
0350         callback->movieParams (0, 0, movie_width, movie_height, 1.0*movie_width/movie_height, QStringList (), QStringList ());
0351     XLockDisplay (display);
0352     if (!running && XvGrabPort (display, xvport, CurrentTime) == Success) {
0353         gc = XCreateGC (display, wid, 0, NULL);
0354         XvSelectPortNotify (display, xvport, 1);
0355         XvSelectVideoNotify (display, wid, 1);
0356         int nr, cur_val;
0357         if (XvGetPortAttribute (display, xvport, xv_autopaint_colorkey_atom, &cur_val) == Success && cur_val == 0) {
0358             fprintf (stderr, "XV_AUTOPAINT_COLORKEY is 0\n");
0359             XvSetPortAttribute (display, xvport, xv_autopaint_colorkey_atom, 1);
0360             reset_xv_autopaint_colorkey = true;
0361         }
0362         XvAttribute *attributes = XvQueryPortAttributes (display, xvport, &nr);
0363         if (attributes) {
0364             for (int i = 0; i < nr; i++) {
0365                 Limit * limit = 0;
0366                 Atom atom = XInternAtom (display, attributes[i].name, false);
0367                 if (atom == xv_volume_atom) {
0368                     limit = xv_limits + limit_volume;
0369                     XvGetPortAttribute (display, xvport,
0370                             xv_volume_atom, &current_volume);
0371                 } else if (atom == xv_hue_atom) {
0372                     limit = xv_limits + limit_hue;
0373                 } else if (atom == xv_saturation_atom) {
0374                     limit = xv_limits + limit_saturation;
0375                 } else if (atom == xv_brightness_atom) {
0376                     limit = xv_limits + limit_brightness;
0377                 } else if (atom == xv_contrast_atom) {
0378                     limit = xv_limits + limit_contrast;
0379                 } else
0380                     continue;
0381                 limit->min = attributes[i].min_value;
0382                 limit->max = attributes[i].max_value;
0383             }
0384             XFree (attributes);
0385         }
0386         if (xv_frequency > 0)
0387             XvSetPortAttribute (display, xvport, xv_freq_atom, int (1.0*xv_frequency/62.5));
0388         if (xv_encoding >= 0)
0389             XvSetPortAttribute (display, xvport, xv_enc_atom, xv_encoding);
0390         if (XvGetPortAttribute (display, xvport, xv_mute_atom, &cur_val) ==
0391                 Success && cur_val == 1) {
0392             fprintf (stderr, "XV_MUTE is 1\n");
0393             if (xv_limits[limit_volume].min != xv_limits[limit_volume].max) {
0394                 tmp_volume = xv_limits[limit_volume].min;
0395                 XvSetPortAttribute(display, xvport, xv_volume_atom, tmp_volume);
0396                 mute_timer = startTimer (start_vol_timeout);
0397             }
0398             XvSetPortAttribute (display, xvport, xv_mute_atom, 0);
0399             reset_xv_mute = true;
0400         }
0401         //XvGetVideo (..
0402         running = true;
0403     }
0404     if (running) {
0405         putVideo ();
0406         if (callback) {
0407             callback->playing (0);
0408             callback->statusMessage (0, (int) KMPlayer::Callback::stat_hasvideo, QString ());
0409         }
0410     }
0411     XUnlockDisplay (display);
0412 }
0413 
0414 void KXVideoPlayer::stop () {
0415     if (mute_timer) {
0416         killTimer (mute_timer);
0417         mute_timer = 0;
0418     }
0419     if (running) {
0420         running = false;
0421         XLockDisplay (display);
0422         XvStopVideo (display, xvport, wid);
0423         if (reset_xv_autopaint_colorkey) {
0424             XvSetPortAttribute (display, xvport, xv_autopaint_colorkey_atom, 0);
0425             reset_xv_autopaint_colorkey = false;
0426         }
0427         if (reset_xv_mute) {
0428             XvSetPortAttribute (display, xvport, xv_mute_atom, 1);
0429             reset_xv_mute = false;
0430         }
0431         XvUngrabPort (display, xvport, CurrentTime);
0432         XFreeGC (display, gc);
0433         XClearArea (display, wid, 0, 0, 0, 0, true);
0434         XUnlockDisplay (display);
0435     }
0436     if (callback)
0437         callback->finished (0);
0438     else
0439         QTimer::singleShot (0, qApp, SLOT (quit ()));
0440 }
0441 
0442 void KXVideoPlayer::finished () {
0443     QTimer::singleShot (10, this, SLOT (stop ()));
0444 }
0445 
0446 void KXVideoPlayer::saturation (int val) {
0447     XLockDisplay(display);
0448     XvSetPortAttribute (display, xvport, xv_saturation_atom, val);
0449     XFlush (display);
0450     XUnlockDisplay(display);
0451 }
0452 
0453 void KXVideoPlayer::hue (int val) {
0454     XLockDisplay(display);
0455     XvSetPortAttribute (display, xvport, xv_hue_atom, val);
0456     XFlush (display);
0457     XUnlockDisplay(display);
0458 }
0459 
0460 void KXVideoPlayer::contrast (int val) {
0461     XLockDisplay(display);
0462     XvSetPortAttribute (display, xvport, xv_contrast_atom, val);
0463     XFlush (display);
0464     XUnlockDisplay(display);
0465 }
0466 
0467 void KXVideoPlayer::brightness (int val) {
0468     XLockDisplay(display);
0469     XvSetPortAttribute (display, xvport, xv_brightness_atom, val);
0470     XFlush (display);
0471     XUnlockDisplay(display);
0472 }
0473 
0474 void KXVideoPlayer::volume (int val) {
0475     current_volume = val;
0476     if (mute_timer)
0477         return;
0478     XLockDisplay(display);
0479     XvSetPortAttribute (display, xvport, xv_volume_atom, val);
0480     XFlush (display);
0481     XUnlockDisplay(display);
0482 }
0483 
0484 void KXVideoPlayer::frequency (int val) {
0485     // this doesn't work, changing frequency kills audio for me
0486     if (mute_timer) {
0487         killTimer (mute_timer);
0488         mute_timer = 0;
0489     }
0490     xv_frequency = val;
0491     if (running && have_freq) {
0492         XLockDisplay(display);
0493         if (xv_limits[limit_volume].min != xv_limits[limit_volume].max) {
0494             tmp_volume = xv_limits[limit_volume].min;
0495             XvSetPortAttribute (display, xvport, xv_volume_atom, tmp_volume);
0496             mute_timer = startTimer (start_vol_timeout);
0497             XFlush (display);
0498             XvSetPortAttribute (display, xvport, xv_mute_atom, 0);
0499         }
0500         XvSetPortAttribute (display, xvport, xv_freq_atom, int (1.0*val/6.25));
0501         XFlush (display);
0502         XUnlockDisplay(display);
0503     }
0504 }
0505 
0506 void KXVideoPlayer::saveState (QSessionManager & sm) {
0507     if (callback)
0508         sm.setRestartHint (QSessionManager::RestartNever);
0509 }
0510 
0511 void KXVideoPlayer::timerEvent (QTimerEvent * e) {
0512     if (e->timerId () == mute_timer) {
0513         int step = (current_volume - xv_limits[limit_volume].min) / 20;
0514         if (step > 0 && tmp_volume == xv_limits[limit_volume].min) {
0515             killTimer (mute_timer);
0516             mute_timer = startTimer (inc_vol_timeout);
0517         }
0518         tmp_volume += step;
0519         if (tmp_volume >= current_volume || step <= 0) {
0520             tmp_volume = current_volume;
0521             killTimer (mute_timer);
0522             mute_timer = 0;
0523         }
0524         XLockDisplay(display);
0525         XvSetPortAttribute (display, xvport, xv_volume_atom, tmp_volume);
0526         XFlush (display);
0527         XUnlockDisplay(display);
0528     } else
0529         killTimer (e->timerId ());
0530 }
0531 
0532 class XEventThread : public QThread {
0533 protected:
0534     void run () {
0535         Time prev_click_time = 0;
0536         int prev_click_x = 0;
0537         int prev_click_y = 0;
0538         while (true) {
0539             XEvent   xevent;
0540             XNextEvent(display, &xevent);
0541             switch(xevent.type) {
0542                 case ClientMessage:
0543                     if (xevent.xclient.format == 8 &&
0544                             !strncmp(xevent.xclient.data.b, "quit_now", 8)) {
0545                         fprintf(stderr, "request quit\n");
0546                         return;
0547                     }
0548                     break;
0549                 case KeyPress: {
0550                     XKeyEvent  kevent;
0551                     KeySym     ksym;
0552                     char       kbuf[256];
0553                     int        len;
0554                     kevent = xevent.xkey;
0555                     XLockDisplay(display);
0556                     len = XLookupString(&kevent, kbuf, sizeof(kbuf), &ksym, NULL);
0557                     XUnlockDisplay(display);
0558                     fprintf(stderr, "keypressed 0x%x 0x%x\n", ( int ) kevent.keycode, ( int ) ksym);
0559                     switch (ksym) {
0560                         case XK_q:
0561                         case XK_Q:
0562                             xvapp->lock ();
0563                             xvapp->stop ();
0564                             xvapp->unlock ();
0565                             break;
0566                     }
0567                     break;
0568                 }
0569                 case Expose:
0570                     if(xevent.xexpose.count != 0 || xevent.xexpose.window != wid)
0571                         break;
0572                     break;
0573 
0574                 case ConfigureNotify:
0575                     if (::running)
0576                         putVideo ();
0577                     break;
0578                 case XvVideoNotify:
0579                     fprintf (stderr, "xvevent %lu\n", ((XvEvent*)&xevent)->xvvideo.reason);
0580                     break;
0581                 case ButtonPress: {
0582                     XButtonEvent *bev = (XButtonEvent *) &xevent;
0583                     int dx = prev_click_x - bev->x;
0584                     int dy = prev_click_y - bev->y;
0585                     if (bev->time - prev_click_time < 400 &&
0586                             (dx * dx + dy * dy) < 25) {
0587                         xvapp->lock ();
0588                         if (callback)
0589                             callback->toggleFullScreen (0);
0590                         xvapp->unlock ();
0591                     }
0592                     prev_click_time = bev->time;
0593                     prev_click_x = bev->x;
0594                     prev_click_y = bev->y;
0595                     break;
0596                 }
0597                 default:
0598                     if (xevent.type < LASTEvent) {
0599                         //fprintf (stderr, "event %d\n", xevent.type);
0600                     }
0601             }
0602         }
0603     }
0604 };
0605 
0606 int main(int argc, char **argv) {
0607     if (!XInitThreads ()) {
0608         fprintf (stderr, "XInitThreads () failed\n");
0609         return 1;
0610     }
0611     display = XOpenDisplay(NULL);
0612     screen  = XDefaultScreen(display);
0613 
0614     unsigned int ver, rel, req, evb, err;
0615     if (XvQueryExtension (display, &ver, &rel, &req, &evb, &err) != Success) {
0616         fprintf (stderr, "XVideo not supported on display\n");
0617         XCloseDisplay (display);
0618         return 1;
0619     }
0620     xv_enc_atom = XInternAtom (display, "XV_ENCODING", false);
0621     xv_hue_atom = XInternAtom (display, "XV_HUE", false);
0622     xv_saturation_atom = XInternAtom (display, "XV_SATURATION", false);
0623     xv_brightness_atom = XInternAtom (display, "XV_BRIGHTNESS", false);
0624     xv_contrast_atom = XInternAtom (display, "XV_CONTRAST", false);
0625     xv_freq_atom = XInternAtom (display, "XV_FREQ", false);
0626     xv_volume_atom = XInternAtom (display, "XV_VOLUME", false);
0627     xv_mute_atom = XInternAtom (display, "XV_MUTE", false);
0628     xv_autopaint_colorkey_atom = XInternAtom (display, "XV_AUTOPAINT_COLORKEY", false);
0629 
0630     xvapp = new KXVideoPlayer (argc, argv);
0631 
0632     for(int i = 1; i < argc; i++) {
0633         if (!strcmp (argv [i], "-port")) {
0634             xvport = strtol (argv [++i], 0L, 10);
0635         } else if (!strcmp (argv [i], "-wid") || !strcmp (argv [i], "-window-id")) {
0636             wid = atol (argv [++i]);
0637             window_created = false;
0638         } else if (!strcmp (argv [i], "-root")) {
0639             wid =  XDefaultRootWindow (display);
0640             window_created = false;
0641         } else if (!strcmp (argv [i], "-window")) {
0642             ;
0643         } else if (!strcmp (argv [i], "-v")) {
0644             verbose = true;
0645         } else if (!strcmp (argv [i], "-c")) {
0646             wants_config = true;
0647         } else if (!strcmp (argv [i], "-f") && i < argc - 1) {
0648             strncpy (configfile, argv [++i], sizeof (configfile));
0649             configfile[sizeof (configfile) - 1] = 0;
0650         } else if (!strcmp (argv [i], "-cb")) {
0651             QString str = argv [++i];
0652             int pos = str.find ('/');
0653             if (pos > -1) {
0654                 fprintf (stderr, "callback is %s %s\n", str.left (pos).ascii (), str.mid (pos + 1).ascii ());
0655                 callback = new KMPlayer::Callback_stub 
0656                     (str.left (pos).ascii (), str.mid (pos + 1).ascii ());
0657             }
0658         } else if (!strcmp (argv [i], "-enc")) {
0659             xv_encoding = strtol (argv [++i], 0L, 10);
0660         } else if (!strcmp (argv [i], "-norm")) {
0661             xv_norm = argv [++i];
0662         } else if (!strcmp (argv [i], "-freq")) {
0663             xv_frequency = strtol (argv [++i], 0L, 10);
0664         } else  {
0665             fprintf (stderr, "usage: %s [-port <xv port>] [-enc <encoding>] [-freq <frequency>] [-f <config file>] [-v] [(-wid|-window-id) <window>] [(-root|-window)] [-cb <DCOP callback name> [-c]]\n", argv[0]);
0666             delete xvapp;
0667             return 1;
0668         }
0669     }
0670 
0671     DCOPClient dcopclient;
0672     dcopclient.registerAs ("kxvideoplayer");
0673     Backend player;
0674 
0675     XEventThread * eventThread = new XEventThread;
0676     eventThread->start ();
0677 
0678     xvapp->init ();
0679 
0680     if (callback)
0681         callback->started (dcopclient.appId (), config_buf);
0682 
0683     xvapp->exec ();
0684 
0685     XLockDisplay(display);
0686     XClientMessageEvent ev = {
0687         ClientMessage, 0, true, display, wid, 
0688         XInternAtom (display, "XVIDEO", false), 8, {"quit_now"}
0689     };
0690     XSendEvent (display, wid, false, StructureNotifyMask, (XEvent *) & ev);
0691     XFlush (display);
0692     XUnlockDisplay(display);
0693     eventThread->wait (500);
0694     delete eventThread;
0695 
0696     xvapp->stop ();
0697     delete xvapp;
0698 
0699     fprintf (stderr, "closing display\n");
0700     XCloseDisplay (display);
0701     fprintf (stderr, "done\n");
0702     return 0;
0703 }
0704 
0705 #include "xvplayer.moc"