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