00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <iostream>
00016 #include <sys/shm.h>
00017 #include <cstdlib>
00018
00019
00020 #include <qdatetime.h>
00021 #include <qtimer.h>
00022 #include <qsqlquery.h>
00023 #include <qsqldatabase.h>
00024
00025
00026 #include "mythtv/mythcontext.h"
00027
00028
00029 #include "zmliveplayer.h"
00030 #include "zmclient.h"
00031
00032
00033 #define MAX_IMAGE_SIZE (2048*1536*3)
00034
00035 const int FRAME_UPDATE_TIME = 1000 / 10;
00036 const int STATUS_UPDATE_TIME = 1000 / 2;
00037
00038 ZMLivePlayer::ZMLivePlayer(int monitorID, int eventID, MythMainWindow *parent,
00039 const QString &window_name, const QString &theme_filename,
00040 const char *name)
00041 :MythThemedDialog(parent, window_name, theme_filename, name)
00042 {
00043 m_monitorID = monitorID;
00044 m_eventID = eventID;
00045 wireUpTheme();
00046
00047 m_paused = false;
00048
00049 m_players = NULL;
00050 m_monitors = NULL;
00051 m_monitorLayout = 1;
00052
00053 gContext->DoDisableScreensaver();
00054
00055 m_frameTimer = new QTimer(this);
00056 connect(m_frameTimer, SIGNAL(timeout()), this,
00057 SLOT(updateFrame()));
00058
00059 m_statusTimer = new QTimer(this);
00060 connect(m_statusTimer, SIGNAL(timeout()), this,
00061 SLOT(updateMonitorStatus()));
00062
00063 getMonitorList();
00064
00065
00066
00067 QTimer::singleShot(100, this, SLOT(initMonitorLayout()));
00068 }
00069
00070 void ZMLivePlayer::initMonitorLayout()
00071 {
00072
00073 if (m_monitors->size() == 0)
00074 {
00075 MythPopupBox::showOkPopup(gContext->GetMainWindow(), "No monitors",
00076 tr("Cannot find any monitors. Bailing out!"));
00077 reject();
00078 return;
00079 }
00080
00081 setMonitorLayout(gContext->GetNumSetting("ZoneMinderLiveLayout", 1), true);
00082 m_frameTimer->start(FRAME_UPDATE_TIME);
00083 m_statusTimer->start(STATUS_UPDATE_TIME);
00084 }
00085
00086 ZMLivePlayer::~ZMLivePlayer()
00087 {
00088 gContext->SaveSetting("ZoneMinderLiveLayout", m_monitorLayout);
00089
00090 gContext->DoRestoreScreensaver();
00091
00092 if (m_players)
00093 {
00094 QString s = "";
00095 Player *p;
00096 vector<Player*>::iterator i = m_players->begin();
00097 for (; i != m_players->end(); i++)
00098 {
00099 p = *i;
00100 if (s != "")
00101 s += ",";
00102 s += QString("%1").arg(p->getMonitor()->id);
00103 }
00104
00105 gContext->SaveSetting("ZoneMinderLiveCameras", s);
00106 }
00107 else
00108 gContext->SaveSetting("ZoneMinderLiveCameras", "");
00109
00110 if (m_players)
00111 {
00112 stopPlayers();
00113 delete m_players;
00114 }
00115
00116 if (m_monitors)
00117 delete m_monitors;
00118
00119 delete m_frameTimer;
00120 delete m_statusTimer;
00121 }
00122
00123 UITextType* ZMLivePlayer::getTextType(QString name)
00124 {
00125 UITextType* type = getUITextType(name);
00126
00127 if (!type)
00128 {
00129 cout << "ERROR: Failed to find '" << name << "' UI element in theme file\n"
00130 << "Bailing out!" << endl;
00131 exit(0);
00132 }
00133
00134 return type;
00135 }
00136
00137 void ZMLivePlayer::keyPressEvent(QKeyEvent *e)
00138 {
00139 if (!e) return;
00140
00141 bool handled = false;
00142 QStringList actions;
00143 gContext->GetMainWindow()->TranslateKeyPress("TV Playback", e, actions);
00144
00145 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00146 {
00147 QString action = actions[i];
00148 handled = true;
00149
00150 if (action == "PAUSE")
00151 {
00152 if (m_paused)
00153 {
00154 m_frameTimer->start(FRAME_UPDATE_TIME);
00155 m_paused = false;
00156 }
00157 else
00158 {
00159 m_frameTimer->stop();
00160 m_paused = true;
00161 }
00162 }
00163 else if (action == "INFO")
00164 {
00165 m_monitorLayout++;
00166 if (m_monitorLayout > 3)
00167 m_monitorLayout = 1;
00168 setMonitorLayout(m_monitorLayout);
00169 }
00170 else if (action == "1" || action == "2" || action == "3" ||
00171 action == "4" || action == "5" || action == "6" ||
00172 action == "7" || action == "8" || action == "9")
00173 changePlayerMonitor(action.toInt());
00174 else
00175 handled = false;
00176 }
00177
00178 if (!handled)
00179 MythThemedDialog::keyPressEvent(e);
00180 }
00181
00182 void ZMLivePlayer::changePlayerMonitor(int playerNo)
00183 {
00184 if (playerNo > (int)m_players->size())
00185 return;
00186
00187 m_frameTimer->stop();
00188
00189 int oldMonID = m_players->at(playerNo - 1)->getMonitor()->id;
00190 Monitor *mon;
00191
00192
00193 vector<Monitor*>::iterator i = m_monitors->begin();
00194 for (; i != m_monitors->end(); i++)
00195 {
00196 mon = *i;
00197 if (oldMonID == mon->id)
00198 {
00199 break;
00200 }
00201 }
00202
00203
00204 if (i != m_monitors->end())
00205 i++;
00206
00207
00208 if (i == m_monitors->end())
00209 i = m_monitors->begin();
00210
00211 mon = *i;
00212
00213 m_players->at(playerNo - 1)->setMonitor(mon, winId());
00214
00215 UITextType *text = getUITextType(QString("name%1-%2").arg(m_monitorLayout).arg(playerNo));
00216 if (text)
00217 text->SetText(mon->name);
00218
00219 m_frameTimer->start(FRAME_UPDATE_TIME);
00220 }
00221
00222 void ZMLivePlayer::wireUpTheme()
00223 {
00224
00225 m_idleFont = getFont("idle");
00226 m_alarmFont = getFont("alarm");
00227 m_alertFont = getFont("alert");
00228 }
00229
00230 void ZMLivePlayer::updateFrame()
00231 {
00232 class ZMClient *zm = ZMClient::get();
00233 if (!zm)
00234 return;
00235
00236 static unsigned char buffer[MAX_IMAGE_SIZE];
00237 m_frameTimer->stop();
00238
00239
00240 QValueList<int> monList;
00241 Player *p;
00242 vector<Player*>::iterator i = m_players->begin();
00243 for (; i != m_players->end(); i++)
00244 {
00245 p = *i;
00246 if (!monList.contains(p->getMonitor()->id))
00247 monList.append(p->getMonitor()->id);
00248 }
00249
00250 for (uint x = 0; x < monList.count(); x++)
00251 {
00252 QString status;
00253 int frameSize = zm->getLiveFrame(monList[x], status, buffer, sizeof(buffer));
00254
00255 if (frameSize > 0 && !status.startsWith("ERROR"))
00256 {
00257
00258 Player *p;
00259 vector<Player*>::iterator i = m_players->begin();
00260 for (; i != m_players->end(); i++)
00261 {
00262 p = *i;
00263 if (p->getMonitor()->id == monList[x])
00264 {
00265 p->getMonitor()->status = status;
00266 p->updateScreen(buffer);
00267 }
00268 }
00269 }
00270
00271 }
00272
00273 m_frameTimer->start(FRAME_UPDATE_TIME);
00274 }
00275
00276 void ZMLivePlayer::stopPlayers()
00277 {
00278 m_frameTimer->stop();
00279 m_statusTimer->stop();
00280
00281 Player *p;
00282 vector<Player*>::iterator i = m_players->begin();
00283 for (; i != m_players->end(); i++)
00284 {
00285 p = *i;
00286 p->stopPlaying();
00287 }
00288 }
00289
00290 void ZMLivePlayer::setMonitorLayout(int layout, bool restore)
00291 {
00292 QStringList monList = QStringList::split(",",
00293 gContext->GetSetting("ZoneMinderLiveCameras", ""));
00294 m_monitorLayout = layout;
00295
00296 if (m_players)
00297 {
00298 stopPlayers();
00299 delete m_players;
00300 }
00301
00302 m_players = new vector<Player *>;
00303 m_monitorCount = 1;
00304
00305 if (layout == 1)
00306 m_monitorCount = 1;
00307 else if (layout == 2)
00308 m_monitorCount = 2;
00309 else if (layout == 3)
00310 m_monitorCount = 4;
00311 else if (layout == 4)
00312 m_monitorCount = 9;
00313
00314 uint monitorNo = 1;
00315
00316 for (int x = 1; x <= m_monitorCount; x++)
00317 {
00318 Monitor *monitor = NULL;
00319
00320 if (restore)
00321 {
00322 if (x <= (int) monList.size())
00323 {
00324 QString s = *monList.at(x - 1);
00325 int monID = s.toInt();
00326
00327
00328 vector<Monitor*>::iterator i = m_monitors->begin();
00329 for (; i != m_monitors->end(); i++)
00330 {
00331 if ((*i)->id == monID)
00332 {
00333 monitor = *i;
00334 break;
00335 }
00336 }
00337 }
00338 }
00339
00340 if (!monitor)
00341 monitor = m_monitors->at(monitorNo - 1);
00342
00343 UIImageType *frameImage = getUIImageType(QString("frame%1-%2").arg(layout).arg(x));
00344 if (frameImage)
00345 {
00346 QPoint pos = frameImage->DisplayPos();
00347 QSize size = frameImage->GetSize(true);
00348 Player *p = new Player();
00349 p->setDisplayRect(QRect(pos.x(), pos.y(), size.width(), size.height()));
00350 p->startPlayer(monitor, winId());
00351 m_players->push_back(p);
00352 }
00353
00354 UITextType *text = getUITextType(QString("name%1-%2").arg(layout).arg(x));
00355 if (text)
00356 text->SetText(monitor->name);
00357
00358 monitorNo++;
00359 if (monitorNo > m_monitors->size())
00360 monitorNo = 1;
00361 }
00362
00363 setContext(layout);
00364 updateForeground();
00365
00366 updateFrame();
00367 m_statusTimer->start(STATUS_UPDATE_TIME);
00368 }
00369
00370 void ZMLivePlayer::getMonitorList(void)
00371 {
00372 if (!m_monitors)
00373 m_monitors = new vector<Monitor *>;
00374
00375 m_monitors->clear();
00376
00377 if (class ZMClient *zm = ZMClient::get())
00378 zm->getMonitorList(m_monitors);
00379 }
00380
00381 void ZMLivePlayer::updateMonitorStatus()
00382 {
00383 m_statusTimer->stop();
00384
00385 for (int x = 1; x <= (int) m_players->size(); x++)
00386 {
00387 Monitor *monitor = m_players->at(x-1)->getMonitor();
00388
00389 UITextType *text = getUITextType(QString("status%1-%2").arg(m_monitorLayout).arg(x));
00390 if (text)
00391 {
00392 if (monitor->status == "Alarm" || monitor->status == "Error")
00393 text->SetFont(m_alarmFont);
00394 else if (monitor->status == "Alert")
00395 text->SetFont(m_alertFont);
00396 else
00397 text->SetFont(m_idleFont);
00398
00399 text->SetText(monitor->status);
00400 }
00401 }
00402
00403 m_statusTimer->start(STATUS_UPDATE_TIME);
00404 }
00405
00406
00408
00409 #define TEXTURE_WIDTH 1024
00410 #define TEXTURE_HEIGHT 1024
00411
00412 Player::Player()
00413 {
00414 m_initalized = false;
00415 m_useGL = (gContext->GetNumSetting("ZoneMinderUseOpenGL", 1) == 1);
00416 m_XvImage = NULL;
00417 m_XImage = NULL;
00418
00419 if (m_useGL)
00420 VERBOSE(VB_GENERAL, "MythZoneMinder: Using openGL for display");
00421 else
00422 VERBOSE(VB_GENERAL, "MythZoneMinder: Using Xv for display");
00423 }
00424
00425 Player::~Player()
00426 {
00427 }
00428
00429 void Player::setMonitor(Monitor *mon, Window winID)
00430 {
00431 stopPlaying();
00432 m_monitor = *mon;
00433 startPlayer(&m_monitor, winID);
00434 }
00435
00436 bool Player::startPlayer(Monitor *mon, Window winID)
00437 {
00438 bool res;
00439
00440 if (m_useGL)
00441 res = startPlayerGL(mon, winID);
00442 else
00443 res = startPlayerXv(mon, winID);
00444
00445 return res;
00446 }
00447
00448 bool Player::startPlayerGL(Monitor *mon, Window winID)
00449 {
00450 m_initalized = false;
00451
00452 m_monitor = *mon;
00453
00454 Window parent = winID;
00455
00456 m_dis = XOpenDisplay(gContext->GetX11Display());
00457 if (m_dis == NULL)
00458 {
00459 VERBOSE(VB_IMPORTANT, "MythZoneMinder: Unable to open display\n");
00460 m_monitor.status = "Error";
00461 return false;
00462 }
00463
00464 m_screenNum = DefaultScreen(m_dis);
00465
00466 if (!glXQueryExtension(m_dis, NULL, NULL))
00467 {
00468 VERBOSE(VB_IMPORTANT, "MythZoneMinder: X server has no OpenGL GLX extension");
00469 m_monitor.status = "Error";
00470 return false;
00471 }
00472
00473 int configuration[] = {GLX_DOUBLEBUFFER,GLX_RGBA,GLX_DEPTH_SIZE, 24, None};
00474 XVisualInfo *vi;
00475
00476 vi = glXChooseVisual(m_dis, m_screenNum, configuration);
00477 if (vi==NULL)
00478 {
00479 VERBOSE(VB_IMPORTANT, "MythZoneMinder: No appropriate RGB visual with depth buffer");
00480 m_monitor.status = "Error";
00481 return false;
00482 }
00483
00484 m_cx = glXCreateContext(m_dis, vi, NULL, GL_TRUE);
00485 if (m_cx == NULL)
00486 {
00487 VERBOSE(VB_IMPORTANT, "MythZoneMinder: Couldn't create rendering context");
00488 m_monitor.status = "Error";
00489 return false;
00490 }
00491
00492 glDisable(GL_ALPHA_TEST);
00493 glDisable(GL_BLEND);
00494 glDisable(GL_DEPTH_TEST);
00495 glDisable(GL_DITHER);
00496 glDisable(GL_FOG);
00497 glDisable(GL_LIGHTING);
00498 glDisable(GL_LOGIC_OP);
00499 glDisable(GL_STENCIL_TEST);
00500 glDisable(GL_TEXTURE_1D);
00501 glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
00502 glPixelTransferi(GL_RED_SCALE, 1);
00503 glPixelTransferi(GL_RED_BIAS, 0);
00504 glPixelTransferi(GL_GREEN_SCALE, 1);
00505 glPixelTransferi(GL_GREEN_BIAS, 0);
00506 glPixelTransferi(GL_BLUE_SCALE, 1);
00507 glPixelTransferi(GL_BLUE_BIAS, 0);
00508 glPixelTransferi(GL_ALPHA_SCALE, 1);
00509 glPixelTransferi(GL_ALPHA_BIAS, 0);
00510
00511 m_win = XCreateSimpleWindow (m_dis, parent,
00512 m_displayRect.x(), m_displayRect.y(),
00513 m_displayRect.width(), m_displayRect.height(),
00514 2, 0, 0);
00515
00516 if (m_win == None)
00517 {
00518 VERBOSE(VB_IMPORTANT, "MythZoneMinder: Unable to create window\n");
00519 m_monitor.status = "Error";
00520 return false;
00521 }
00522
00523 XMapWindow (m_dis, m_win);
00524 XMoveWindow(m_dis, m_win, m_displayRect.x(), m_displayRect.y());
00525
00526 glXMakeCurrent(m_dis, m_win, m_cx);
00527
00528 glTexImage2D(GL_TEXTURE_2D, 0, 3, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGB,
00529 GL_UNSIGNED_BYTE, NULL);
00530 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00531 glEnable(GL_TEXTURE_2D);
00532 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
00533 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
00534 glShadeModel(GL_FLAT);
00535
00536 m_initalized = true;
00537 return true;
00538 }
00539
00540 bool Player::startPlayerXv(Monitor *mon, Window winID)
00541 {
00542 bool useXV = true;
00543 m_initalized = false;
00544
00545 m_monitor = *mon;
00546
00547 Window parent = winID;
00548
00549 m_dis = XOpenDisplay(gContext->GetX11Display());
00550 if (m_dis == NULL)
00551 {
00552 VERBOSE(VB_IMPORTANT, "MythZoneMinder: Unable to open display\n");
00553 m_monitor.status = "Error";
00554 return false;
00555 }
00556
00557 m_screenNum = DefaultScreen(m_dis);
00558
00559 m_win = XCreateSimpleWindow (m_dis, parent,
00560 m_displayRect.x(), m_displayRect.y(),
00561 m_displayRect.width(), m_displayRect.height(),
00562 2, 0, 0);
00563
00564 if (m_win == None)
00565 {
00566 VERBOSE(VB_IMPORTANT, "MythZoneMinder: Unable to create window\n");
00567 m_monitor.status = "Error";
00568 return false;
00569 }
00570
00571 XMapWindow (m_dis, m_win);
00572 XMoveWindow(m_dis, m_win, m_displayRect.x(), m_displayRect.y());
00573
00574 m_XVport = -1;
00575
00576 m_gc = XCreateGC(m_dis, m_win, 0, NULL);
00577 if (m_gc ==NULL)
00578 {
00579 VERBOSE(VB_IMPORTANT, "MythZoneMinder: Unable to create gc");
00580 m_monitor.status = "Error";
00581 return false;
00582 }
00583
00584 m_rgba = (char *) malloc(m_displayRect.width() * m_displayRect.height() * 4);
00585
00586 m_haveXV = useXV;
00587
00588 if (useXV)
00589 {
00590 m_XVport = getXvPortId(m_dis);
00591 if (m_XVport == -1)
00592 {
00593 VERBOSE(VB_GENERAL, "WARNING: Couldn't find free Xv adaptor with RGB XvImage support");
00594 VERBOSE(VB_GENERAL, "Falling back to XImage - slow and ugly rescaling");
00595 m_haveXV = false;
00596 }
00597 else
00598 VERBOSE(VB_GENERAL, "MythZoneMinder: Using Xv for scaling");
00599 }
00600 else
00601 VERBOSE(VB_GENERAL, "MythZoneMinder: Forcing use of software scaling");
00602
00603 m_initalized = true;
00604 return true;
00605 }
00606
00607 int Player::getXvPortId(Display *dpy)
00608 {
00609 int portNum, numImages;
00610 unsigned int i, j, k, numAdapt;
00611 XvImageFormatValues *formats;
00612 XvAdaptorInfo *info;
00613
00614 portNum = -1;
00615
00616 if (Success != XvQueryAdaptors(dpy, DefaultRootWindow(dpy), &numAdapt, &info))
00617 {
00618 VERBOSE(VB_IMPORTANT, "No Xv adaptors found!");
00619 return -1;
00620 }
00621
00622 VERBOSE(VB_GENERAL, QString("Found %1 Xv adaptors").arg(numAdapt));
00623
00624 for (i = 0; i < numAdapt; i++)
00625 {
00626 if (info[i].type & XvImageMask)
00627 {
00628
00629 formats = XvListImageFormats(dpy, info[i].base_id, &numImages);
00630
00631 for (j = 0; j < (unsigned int) numImages; j++)
00632 {
00633 if (formats[j].id == RGB24)
00634 {
00635
00636 for (k = 0; k < info[i].num_ports; k++)
00637 {
00638
00639 if (Success == XvGrabPort(dpy, info[i].base_id + k, CurrentTime))
00640 {
00641 portNum = info[i].base_id + k;
00642 break;
00643 }
00644 }
00645 }
00646 if (portNum != -1)
00647 break;
00648 }
00649 XFree(formats);
00650 }
00651 if (portNum != -1)
00652 break;
00653 }
00654
00655 XvFreeAdaptorInfo(info);
00656 return portNum;
00657 }
00658
00659 void Player::stopPlaying(void)
00660 {
00661 if (!m_initalized)
00662 return;
00663
00664 if (m_useGL)
00665 glXDestroyContext(m_dis, m_cx);
00666 else
00667 {
00668 if (m_XVport != -1)
00669 XvUngrabPort(m_dis, m_XVport, CurrentTime);
00670 XFreeGC(m_dis, m_gc);
00671
00672 if (m_XImage)
00673 {
00674 XDestroyImage(m_XImage);
00675 m_XImage = NULL;
00676 }
00677
00678 if (m_XvImage)
00679 {
00680 XFree(m_XvImage);
00681 m_XvImage = NULL;
00682 }
00683
00684
00685
00686 }
00687
00688 XDestroyWindow(m_dis, m_win);
00689 XCloseDisplay(m_dis);
00690 }
00691
00692 void Player::updateScreen(const unsigned char* buffer)
00693 {
00694 if (m_useGL)
00695 updateScreenGL(buffer);
00696 else
00697 updateScreenXv(buffer);
00698 }
00699
00700 void Player::updateScreenGL(const unsigned char* buffer)
00701 {
00702 if (!m_initalized)
00703 return;
00704
00705 glXMakeCurrent(m_dis, m_win, m_cx);
00706
00707 if (m_monitor.palette == MP_GREY)
00708 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_monitor.width, m_monitor.height,
00709 GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer);
00710 else
00711 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_monitor.width, m_monitor.height,
00712 GL_RGB, GL_UNSIGNED_BYTE, buffer);
00713
00714 glViewport(0, 0, m_displayRect.width(), m_displayRect.height());
00715
00716 glLoadIdentity();
00717 glTranslatef(-1.0,1.0,0.0);
00718 glScalef((GLfloat)TEXTURE_WIDTH / (GLfloat) m_monitor.width,
00719 -(GLfloat)TEXTURE_HEIGHT / (GLfloat) m_monitor.height, 1);
00720 glBegin(GL_QUADS);
00721 glTexCoord2f(0.0,0.0); glVertex2f(0,0);
00722 glTexCoord2f(0.0,1.0); glVertex2f(0,2);
00723 glTexCoord2f(1.0,1.0); glVertex2f(2,2);
00724 glTexCoord2f(1.0,0.0); glVertex2f(2,0);
00725 glEnd();
00726 glXSwapBuffers(m_dis,m_win);
00727 }
00728
00729 void Player::updateScreenXv(const unsigned char* buffer)
00730 {
00731 if (!m_initalized)
00732 return;
00733
00734 if (m_haveXV && !m_XvImage)
00735 {
00736 m_XvImage = XvCreateImage(m_dis, m_XVport, RGB24, m_rgba,
00737 m_monitor.width, m_monitor.height);
00738 if (m_XvImage == NULL)
00739 {
00740 VERBOSE(VB_GENERAL, "WARNING: Unable to create XVImage");
00741 VERBOSE(VB_GENERAL, "Falling back to XImage - slow and ugly rescaling");
00742 m_haveXV = false;
00743 }
00744 }
00745
00746 if (!m_haveXV && !m_XImage)
00747 {
00748 m_XImage = XCreateImage(m_dis, XDefaultVisual(m_dis, m_screenNum), 24, ZPixmap, 0,
00749 m_rgba, m_displayRect.width(), m_displayRect.height(),
00750 32, 4 * m_displayRect.width());
00751 if (m_XImage == NULL)
00752 {
00753 VERBOSE(VB_IMPORTANT, "ERROR: Unable to create XImage");
00754 return;
00755 }
00756 }
00757
00758 unsigned int pos_data;
00759 unsigned int pos_rgba = 0;
00760 unsigned int r,g,b;
00761
00762 if (m_haveXV)
00763 {
00764 if (m_monitor.palette == MP_GREY)
00765 {
00766
00767 for (pos_data = 0; pos_data < (unsigned int) (m_monitor.width * m_monitor.height); )
00768 {
00769 m_rgba[pos_rgba++] = buffer[pos_data];
00770 m_rgba[pos_rgba++] = buffer[pos_data];
00771 m_rgba[pos_rgba++] = buffer[pos_data++];
00772 pos_rgba++;
00773 }
00774 }
00775 else
00776 {
00777
00778 for (pos_data = 0; pos_data < (unsigned int) (m_monitor.width * m_monitor.height * 3); )
00779 {
00780 r = buffer[pos_data++];
00781 g = buffer[pos_data++];
00782 b = buffer[pos_data++];
00783 m_rgba[pos_rgba++] = b;
00784 m_rgba[pos_rgba++] = g;
00785 m_rgba[pos_rgba++] = r;
00786 pos_rgba++;
00787 }
00788 }
00789
00790 XvPutImage(m_dis, m_XVport, m_win, m_gc, m_XvImage, 0, 0,
00791 m_monitor.width, m_monitor.height,
00792 0, 0, m_displayRect.width(), m_displayRect.height());
00793 }
00794 else
00795 {
00796
00797 for (int y = 0; y < m_displayRect.height(); y++)
00798 {
00799 for (int x = 0; x < m_displayRect.width(); x++)
00800 {
00801
00802 pos_data = y * m_monitor.height / m_displayRect.height();
00803 pos_data = pos_data * m_monitor.width;
00804 pos_data = pos_data + x * m_monitor.width / m_displayRect.width();
00805
00806 if (m_monitor.palette == MP_GREY)
00807 {
00808 m_rgba[pos_rgba++] = buffer[pos_data];
00809 m_rgba[pos_rgba++] = buffer[pos_data];
00810 m_rgba[pos_rgba++] = buffer[pos_data++];
00811 m_rgba[pos_rgba++] = 0;
00812 }
00813
00814 if (m_monitor.palette != MP_GREY)
00815 {
00816
00817 pos_data = pos_data * 3;
00818 r = buffer[pos_data++];
00819 g = buffer[pos_data++];
00820 b = buffer[pos_data++];
00821 m_rgba[pos_rgba++] = b;
00822 m_rgba[pos_rgba++] = g;
00823 m_rgba[pos_rgba++] = r;
00824 m_rgba[pos_rgba++] = 0;
00825 }
00826 }
00827 }
00828
00829 XPutImage(m_dis, m_win, m_gc, m_XImage, 0, 0, 0, 0,
00830 m_displayRect.width(), m_displayRect.height());
00831 }
00832 }