00001
00002
00003
00004
00005
00006
00007 #include <sys/ioctl.h>
00008 #include <fcntl.h>
00009 #include <unistd.h>
00010
00011
00012 #include <linux/fb.h>
00013 extern "C" {
00014 #include <directfb.h>
00015 #include <directfb_version.h>
00016 }
00017
00018
00019 #include <algorithm>
00020 #include <iostream>
00021 using namespace std;
00022
00023
00024 #include <qapplication.h>
00025 #include <qwidget.h>
00026 #include <qevent.h>
00027 #include <qmutex.h>
00028
00029
00030 #include "mythcontext.h"
00031 #include "filtermanager.h"
00032 #include "videoout_directfb.h"
00033 #include "frame.h"
00034 #include "tv.h"
00035
00036 #define LOC QString("DirectFB: ")
00037 #define LOC_WARN QString("DirectFB, Warning: ")
00038 #define LOC_ERR QString("DirectFB, Error: ")
00039
00040 #define ENOFB QString("\n\t\t\tFB Error: %1").arg(DirectFBErrorString(fberr))
00041
00042 static DFBEnumerationResult layer_cb(unsigned int id,
00043 DFBDisplayLayerDescription desc,
00044 void *data);
00045
00046 class QtKey
00047 {
00048 public:
00049 QtKey() : key(0xffff), ascii(0x00) { }
00050 QtKey(int k, int a) : key(k), ascii(a) { }
00051
00052 int key;
00053 int ascii;
00054 };
00055
00056 static void init_keymap(QMap<uint,QtKey> &qtKeyMap);
00057
00058 #ifndef DSCAPS_DOUBLE
00059 #define DSCAPS_DOUBLE DSCAPS_FLIPPING
00060 #endif
00061
00062
00063 const int kNumBuffers = 31;
00064 const int kNeedFreeFrames = 1;
00065 const int kPrebufferFramesNormal = 12;
00066 const int kPrebufferFramesSmall = 4;
00067 const int kKeepPrebuffer = 2;
00068 typedef QMap<unsigned char*, IDirectFBSurface*> BufferMap;
00069
00070 class DirectfbData
00071 {
00072 public:
00073 DirectfbData()
00074 : dfb(NULL), primaryLayer(NULL),
00075 primarySurface(NULL), videoLayer(NULL),
00076 videoSurface(NULL), inputbuf(NULL),
00077 screen_width(0), screen_height(0),
00078 bufferLock(true), has_blit(false)
00079 {
00080 bzero(&videoLayerDesc, sizeof(DFBDisplayLayerDescription));
00081 bzero(&videoLayerConfig, sizeof(DFBDisplayLayerConfig));
00082 bzero(&videoSurfaceCapabilities, sizeof(DFBSurfaceCapabilities));
00083 init_keymap(qtKeyMap);
00084 }
00085
00086 bool CreateBuffers(VideoBuffers &vbuffers, DFBSurfaceDescription);
00087 void DeleteBuffers(VideoBuffers &vbuffers);
00088
00089 IDirectFB *dfb;
00090 IDirectFBDisplayLayer *primaryLayer;
00091 IDirectFBSurface *primarySurface;
00092 IDirectFBDisplayLayer *videoLayer;
00093 IDirectFBSurface *videoSurface;
00094 IDirectFBEventBuffer *inputbuf;
00095 int screen_width;
00096 int screen_height;
00097 BufferMap buffers;
00098 QMutex bufferLock;
00099 DFBDisplayLayerDescription videoLayerDesc;
00100 DFBDisplayLayerConfig videoLayerConfig;
00101 DFBSurfaceCapabilities videoSurfaceCapabilities;
00102 bool has_blit;
00103 QMap<uint,QtKey> qtKeyMap;
00104 };
00105
00106 bool DirectfbData::CreateBuffers(VideoBuffers &vbuffers,
00107 DFBSurfaceDescription desc)
00108 {
00109 VERBOSE(VB_IMPORTANT, "CreateBuffers");
00110
00111 QMutexLocker locker(&bufferLock);
00112
00113 if (!dfb)
00114 return false;
00115
00116
00117 desc.flags = (DFBSurfaceDescriptionFlags)(desc.flags | DSDESC_CAPS);
00118 desc.caps = DSCAPS_SYSTEMONLY;
00119
00120 vector<unsigned char*> bufs;
00121 vector<YUVInfo> yuvinfo;
00122
00123 DFBResult fberr = DFB_OK;
00124
00125 for (uint i = 0; i < vbuffers.allocSize(); i++)
00126 {
00127 IDirectFBSurface *bufferSurface = NULL;
00128
00129 fberr = dfb->CreateSurface(dfb, &desc, &bufferSurface);
00130 if (DFB_OK != fberr)
00131 {
00132 VERBOSE(VB_IMPORTANT, LOC_ERR + "CreateSurface" + ENOFB);
00133 break;
00134 }
00135
00136 void *ptr = NULL;
00137 int pitches[3];
00138
00139 fberr = bufferSurface->Lock(bufferSurface, DSLF_WRITE, &ptr,
00140 &pitches[0]);
00141 if (DFB_OK != fberr)
00142 {
00143 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to lock buffer" + ENOFB);
00144 fberr = bufferSurface->Release(bufferSurface);
00145 if (DFB_OK != fberr)
00146 {
00147 VERBOSE(VB_IMPORTANT, LOC_ERR +
00148 "Failed to release buffer" + ENOFB);
00149 }
00150 break;
00151 }
00152
00153 unsigned char *bufferSurfaceData = (unsigned char*) ptr;
00154 buffers[bufferSurfaceData] = bufferSurface;
00155
00156 pitches[1] = pitches[0] >> 1;
00157 pitches[2] = pitches[0] >> 1;
00158
00159 int offsets[3];
00160 offsets[0] = 0;
00161 offsets[1] = pitches[0] * desc.height;
00162 offsets[2] = offsets[1] + pitches[1] * (desc.height >> 1);
00163
00164 int size = offsets[2] + pitches[2] * (desc.height >> 1);
00165
00166 if (DSPF_YV12 == desc.pixelformat)
00167 {
00168 swap(pitches[1], pitches[2]);
00169 swap(offsets[1], offsets[2]);
00170 }
00171
00172 YUVInfo tmp(desc.width, desc.height, size, pitches, offsets);
00173
00174 bufs.push_back(bufferSurfaceData);
00175 yuvinfo.push_back(tmp);
00176
00177 fberr = bufferSurface->Unlock(bufferSurface);
00178 if (DFB_OK != fberr)
00179 {
00180 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to unlock buffer" + ENOFB);
00181 break;
00182 }
00183 }
00184
00185 if (DFB_OK != fberr)
00186 {
00187 for (uint i = 0; i < bufs.size(); i++)
00188 {
00189 BufferMap::iterator it = buffers.find(bufs[i]);
00190 if (it != buffers.end())
00191 {
00192 IDirectFBSurface *surf = *it;
00193
00194 fberr = surf->Unlock(surf);
00195 if (DFB_OK != fberr)
00196 {
00197 VERBOSE(VB_IMPORTANT, LOC_ERR +
00198 "Failed to unlock buffer" + ENOFB);
00199 }
00200
00201 fberr = surf->Release(surf);
00202 if (DFB_OK != fberr)
00203 {
00204 VERBOSE(VB_IMPORTANT, LOC_ERR +
00205 "Failed to release buffer" + ENOFB);
00206 }
00207
00208 buffers.erase(it);
00209 }
00210 }
00211 return false;
00212 }
00213
00214 bool ok = vbuffers.CreateBuffers(desc.width, desc.height, bufs, yuvinfo);
00215
00216 return ok;
00217 }
00218
00219 void DirectfbData::DeleteBuffers(VideoBuffers &vbuffers)
00220 {
00221 QMutexLocker locker(&bufferLock);
00222
00223 for (uint i = 0; i < vbuffers.allocSize(); i++)
00224 {
00225 vbuffers.at(i)->buf = NULL;
00226
00227 if (vbuffers.at(i)->qscale_table)
00228 {
00229 delete [] vbuffers.at(i)->qscale_table;
00230 vbuffers.at(i)->qscale_table = NULL;
00231 }
00232 }
00233
00234 BufferMap::iterator it;
00235 for (it = buffers.begin() ; it != buffers.end() ; it++)
00236 {
00237 IDirectFBSurface *surf = *it;
00238 if (surf)
00239 {
00240 DFBResult fberr = surf->Unlock(surf);
00241 if (DFB_OK != fberr)
00242 {
00243 VERBOSE(VB_IMPORTANT, LOC_ERR +
00244 "Failed to unlock buffer" + ENOFB);
00245 }
00246
00247 fberr = surf->Release(surf);
00248 if (DFB_OK != fberr)
00249 {
00250 VERBOSE(VB_IMPORTANT, LOC_ERR +
00251 "Failed to release buffer" + ENOFB);
00252 }
00253 }
00254 }
00255
00256 buffers.clear();
00257 }
00258
00259 VideoOutputDirectfb::VideoOutputDirectfb(void)
00260 : VideoOutput(), XJ_started(false), widget(NULL),
00261 data(new DirectfbData())
00262 {
00263 init(&pauseFrame, FMT_YV12, NULL, 0, 0, 0, 0);
00264 }
00265
00266 VideoOutputDirectfb::~VideoOutputDirectfb()
00267 {
00268 if (!data)
00269 return;
00270
00271 data->DeleteBuffers(vbuffers);
00272
00273
00274 if (data->inputbuf)
00275 data->inputbuf->Release(data->inputbuf);
00276 if (data->videoSurface)
00277 data->videoSurface->Release(data->videoSurface);
00278 if (data->primarySurface)
00279 data->primarySurface->Release(data->primarySurface);
00280 if (data->primaryLayer)
00281 data->primaryLayer->Release(data->primaryLayer);
00282 if (data->videoLayer)
00283 data->videoLayer->Release(data->videoLayer);
00284 if (data->dfb)
00285 data->dfb->Release(data->dfb);
00286
00287 if (pauseFrame.buf)
00288 {
00289 delete [] pauseFrame.buf;
00290 init(&pauseFrame, FMT_YV12, NULL, 0, 0, 0, 0);
00291 }
00292
00293 XJ_started = false;
00294
00295 delete data;
00296 data = NULL;
00297 }
00298
00299 int VideoOutputDirectfb::GetRefreshRate(void)
00300 {
00301 int fh, v;
00302 struct fb_var_screeninfo si;
00303 double drate;
00304 double hrate;
00305 double vrate;
00306 long htotal;
00307 long vtotal;
00308 char *fb_dev_name = NULL;
00309 if (!fb_dev_name && !(fb_dev_name = getenv("FRAMEBUFFER")))
00310 fb_dev_name = strdup("/dev/fb0");
00311
00312 fh = open(fb_dev_name, O_RDONLY);
00313 if (-1 == fh) {
00314 return -1;
00315 }
00316
00317 if (ioctl(fh, FBIOGET_VSCREENINFO, &si)) {
00318 close(fh);
00319 return -1;
00320 }
00321
00322 htotal = si.left_margin + si.xres + si.right_margin + si.hsync_len;
00323 vtotal = si.upper_margin + si.yres + si.lower_margin + si.vsync_len;
00324
00325 switch (si.vmode & FB_VMODE_MASK) {
00326 case FB_VMODE_INTERLACED:
00327 break;
00328 case FB_VMODE_DOUBLE:
00329 vtotal <<= 2;
00330 break;
00331 default:
00332 vtotal <<= 1;
00333 break;
00334 }
00335
00336 drate = 1E12 / si.pixclock;
00337 hrate = drate / htotal;
00338 vrate = hrate / vtotal * 2;
00339
00340 v = (int)(1E3 / vrate + 0.5);
00341
00342
00343 close(fh);
00344 return v;
00345 }
00346
00348 static QSize fix_alignment(QSize raw)
00349 {
00350 return QSize((raw.width() + 15) & (~0xf),
00351 (raw.height() + 15) & (~0xf));
00352 }
00353
00354 bool VideoOutputDirectfb::Init(int width, int height, float aspect, WId winid,
00355 int winx, int winy, int winw, int winh,
00356 WId embedid)
00357 {
00358
00359 if ((winw < 320) || (winh < 240))
00360 {
00361 return false;
00362 }
00363
00364 widget = QWidget::find(winid);
00365
00366
00367 DFBResult fberr = DirectFBInit(NULL, NULL);
00368 if (DFB_OK != fberr)
00369 {
00370 return false;
00371 }
00372
00373 DirectFBSetOption("bg-none", NULL);
00374 DirectFBSetOption("no-cursor", NULL);
00375
00376 fberr = DirectFBCreate(&(data->dfb));
00377 if (DFB_OK != fberr)
00378 {
00379 return false;
00380 }
00381
00382 fberr = data->dfb->SetCooperativeLevel(data->dfb, DFSCL_FULLSCREEN);
00383 if (DFB_OK != fberr)
00384 {
00385 return false;
00386 }
00387
00388
00389 fberr = data->dfb->GetDisplayLayer(
00390 data->dfb, DLID_PRIMARY, &(data->primaryLayer));
00391 if (DFB_OK != fberr)
00392 {
00393 return false;
00394 }
00395
00396 DFBDisplayLayerConfig conf;
00397 fberr = data->primaryLayer->GetConfiguration(data->primaryLayer, &conf);
00398 if (DFB_OK != fberr)
00399 {
00400 return false;
00401 }
00402
00403 if ((winw != conf.width) || (winh != conf.height))
00404 {
00405 VERBOSE(VB_IMPORTANT, LOC_WARN + "Window size mismatch "
00406 <<QString("%1x%2 -> %3x%4")
00407 .arg(winw).arg(winh).arg(conf.width).arg(conf.height));
00408 }
00409
00410 display_visible_rect = QRect(winx, winy, conf.width, conf.height);
00411
00412
00413 display_dim = db_display_dim;
00414
00415 if (!display_dim.height() || !display_dim.width())
00416 display_dim = QSize(400, 300);
00417
00418 display_aspect =
00419 ((float)(display_dim.width())) / ((float)(display_dim.height()));
00420
00421 VERBOSE(VB_PLAYBACK, LOC +
00422 QString("output : screen pixel size %1x%2")
00423 .arg(display_visible_rect.width())
00424 .arg(display_visible_rect.height()));
00425
00426
00427 #if (DIRECTFB_MAJOR_VERSION == 0) && \
00428 (DIRECTFB_MINOR_VERSION <= 9) && \
00429 (DIRECTFB_MICRO_VERSION <= 22)
00430 DFBCardCapabilities info;
00431 bzero(&info, sizeof(DFBCardCapabilities));
00432 fberr = data->dfb->GetCardCapabilities(data->dfb, &info);
00433 #else
00434 DFBGraphicsDeviceDescription info;
00435 bzero(&info, sizeof(DFBGraphicsDeviceDescription));
00436 fberr = data->dfb->GetDeviceDescription(data->dfb, &info);
00437 #endif
00438
00439 if (DFB_OK != fberr)
00440 {
00441 VERBOSE(VB_IMPORTANT, LOC_ERR +
00442 "Failed to query card capabilities" + ENOFB);
00443 return false;
00444 }
00445
00446 data->has_blit = info.acceleration_mask & DFXL_BLIT;
00447 VERBOSE(VB_PLAYBACK,
00448 QString("DirectFB output : card : %1hardware blit support")
00449 .arg(((data->has_blit) ? "" : "No ")));
00450
00451
00452 DFBSurfaceDescription desc;
00453 desc.flags = DSDESC_CAPS;
00454 desc.caps = DSCAPS_PRIMARY;
00455 if (data->has_blit)
00456 desc.caps = (DFBSurfaceCapabilities)(desc.caps | DSCAPS_DOUBLE);
00457
00458 fberr = data->dfb->CreateSurface(
00459 data->dfb, &desc, &(data->primarySurface));
00460 if (DFB_OK != fberr)
00461 {
00462 return false;
00463 }
00464
00465 fberr = data->primarySurface->Clear(data->primarySurface, 0, 0, 0, 0xff);
00466 if (DFB_OK != fberr)
00467 {
00468 return false;
00469 }
00470
00471 fberr = data->primarySurface->Flip(data->primarySurface, 0, DSFLIP_ONSYNC);
00472 if (DFB_OK != fberr)
00473 {
00474 return false;
00475 }
00476
00477 video_dim = fix_alignment(QSize(width, height));
00478
00479
00480
00481
00482 data->videoLayerConfig.flags = (DFBDisplayLayerConfigFlags)
00483 (DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT);
00484 data->videoLayerConfig.width = video_dim.width();
00485 data->videoLayerConfig.height = video_dim.height();
00486 data->videoLayerConfig.pixelformat = DSPF_I420;
00487
00488 fberr = data->dfb->EnumDisplayLayers(data->dfb, layer_cb, data);
00489 if (DFB_OK != fberr)
00490 {
00491 return false;
00492 }
00493
00494 if (!data->videoLayer)
00495 {
00496 data->videoLayerConfig.pixelformat = DSPF_YV12;
00497 fberr = data->dfb->EnumDisplayLayers(data->dfb, layer_cb, data);
00498 if (DFB_OK != fberr)
00499 {
00500 VERBOSE(VB_IMPORTANT, LOC_WARN +
00501 "Failed to enumerate layers" + ENOFB);
00502 }
00503
00504 if (!data->videoLayer)
00505 {
00506 fberr = data->primaryLayer->TestConfiguration(
00507 data->primaryLayer, &(data->videoLayerConfig), NULL);
00508 if (DFB_OK != fberr)
00509 {
00510 VERBOSE(VB_IMPORTANT, LOC_ERR +
00511 "Could not find usable video output layer");
00512
00513 return false;
00514 }
00515
00516 data->primaryLayer->AddRef(data->primaryLayer);
00517 data->videoLayer = data->primaryLayer;
00518 }
00519 }
00520
00521 QString fb_format =
00522 (data->videoLayerConfig.pixelformat == DSPF_I420) ? "I420" : "YV12";
00523
00524
00525 fberr = data->videoLayer->SetCooperativeLevel(
00526 data->videoLayer, DLSCL_EXCLUSIVE);
00527 if (DFB_OK != fberr)
00528 {
00529 return false;
00530 }
00531
00532
00533 data->videoLayerConfig.flags = (DFBDisplayLayerConfigFlags)
00534 (data->videoLayerConfig.flags | DLCONF_BUFFERMODE);
00535
00536
00537 data->videoLayerConfig.buffermode = DLBM_TRIPLE;
00538 if (data->videoLayer->TestConfiguration(
00539 data->videoLayer, &(data->videoLayerConfig), NULL))
00540 {
00541
00542 data->videoLayerConfig.buffermode = DLBM_BACKVIDEO;
00543 if (data->videoLayer->TestConfiguration(
00544 data->videoLayer, &(data->videoLayerConfig), NULL))
00545 {
00546
00547 data->videoLayerConfig.buffermode = DLBM_BACKSYSTEM;
00548 }
00549 }
00550
00551 QString buf_desc =
00552 (data->videoLayerConfig.buffermode == DLBM_TRIPLE) ?
00553 "triple (video memory)" :
00554 ((data->videoLayerConfig.buffermode == DLBM_BACKVIDEO) ?
00555 "double (video memory)" : "double (system memory)");
00556
00557 fberr = data->videoLayer->SetConfiguration(
00558 data->videoLayer, &(data->videoLayerConfig));
00559 if (DFB_OK != fberr)
00560 {
00561 VERBOSE(VB_IMPORTANT, LOC_ERR +
00562 QString("Failed to initialize %1 buffering.")
00563 .arg(buf_desc) + ENOFB);
00564
00565 return false;
00566 }
00567
00568 VERBOSE(VB_PLAYBACK, LOC +
00569 QString("output : videoLayer : %1 : %2x%3, %4, %5 buffering")
00570 .arg(data->videoLayerDesc.name)
00571 .arg(data->videoLayerConfig.width)
00572 .arg(data->videoLayerConfig.height)
00573 .arg(fb_format).arg(buf_desc));
00574
00575
00576 fberr = data->videoLayer->GetSurface(
00577 data->videoLayer, &(data->videoSurface));
00578 if (DFB_OK != fberr)
00579 {
00580 return false;
00581 }
00582
00583 fberr = data->videoSurface->SetBlittingFlags(
00584 data->videoSurface, DSBLIT_NOFX);
00585 if (DFB_OK != fberr)
00586 {
00587 return false;
00588 }
00589
00590 fberr = data->videoSurface->GetCapabilities(
00591 data->videoSurface, &data->videoSurfaceCapabilities);
00592 if (DFB_OK != fberr)
00593 {
00594 return false;
00595 }
00596
00597 VERBOSE(VB_PLAYBACK, LOC + QString("output : videoSurface : %1, %2, %3")
00598 .arg((data->videoSurfaceCapabilities & DSCAPS_VIDEOONLY) ?
00599 "in video memory" : "in sytem memory")
00600 .arg((data->videoSurfaceCapabilities & DSCAPS_PRIMARY) ?
00601 "primary surface" : "no primary surface")
00602 .arg((data->videoSurfaceCapabilities & DSCAPS_INTERLACED) ?
00603 "interlaced" : "not interlaced"));
00604
00605
00606 fberr = data->dfb->CreateInputEventBuffer(
00607 data->dfb, DICAPS_KEYS, (DFBBoolean)1, &(data->inputbuf));
00608 if (DFB_OK != fberr)
00609 {
00610 return false;
00611 }
00612
00613
00614 vbuffers.Init(kNumBuffers, true, kNeedFreeFrames,
00615 kPrebufferFramesNormal, kPrebufferFramesSmall,
00616 kKeepPrebuffer);
00617 desc.flags = (DFBSurfaceDescriptionFlags)
00618 (DSDESC_HEIGHT | DSDESC_WIDTH | DSDESC_PIXELFORMAT);
00619 desc.width = video_dim.width();
00620 desc.height = video_dim.height();
00621 desc.pixelformat = data->videoLayerConfig.pixelformat;
00622
00623 if (!data->CreateBuffers(vbuffers, desc))
00624 {
00625 return false;
00626 }
00627
00628 VERBOSE(VB_PLAYBACK, LOC +
00629 QString("input : %1 videoSurface buffers : %1x%2, %3")
00630 .arg(kNumBuffers).arg(desc.width).arg(desc.height)
00631 .arg(desc.pixelformat == DSPF_I420 ? "I420" : "YV12"));
00632
00633
00634 init(&pauseFrame, vbuffers.GetScratchFrame()->codec,
00635 new unsigned char[vbuffers.GetScratchFrame()->size + 64],
00636 vbuffers.GetScratchFrame()->width, vbuffers.GetScratchFrame()->height,
00637 vbuffers.GetScratchFrame()->bpp, vbuffers.GetScratchFrame()->size,
00638 vbuffers.GetScratchFrame()->pitches,
00639 vbuffers.GetScratchFrame()->offsets);
00640
00641 pauseFrame.frameNumber = vbuffers.GetScratchFrame()->frameNumber;
00642
00643
00644 if (!VideoOutput::Init(width, height, aspect, winid,
00645 display_visible_rect.x(),
00646 display_visible_rect.y(),
00647 display_visible_rect.width(),
00648 display_visible_rect.height(),
00649 embedid))
00650 {
00651 return false;
00652 }
00653
00654 MoveResize();
00655
00656 InitPictureAttributes();
00657
00658
00659 fberr = data->videoLayer->SetOpacity(data->videoLayer, 0xff);
00660 if (DFB_OK != fberr)
00661 {
00662 return false;
00663 }
00664
00665 XJ_started = true;
00666
00667 return true;
00668 }
00669
00670 void VideoOutputDirectfb::PrepareFrame(VideoFrame *frame, FrameScanType)
00671 {
00672 QMutexLocker locker(&data->bufferLock);
00673 DFBResult fberr = DFB_OK;
00674
00675 if (!frame)
00676 frame = vbuffers.GetScratchFrame();
00677
00678 framesPlayed = frame->frameNumber + 1;
00679
00680 IDirectFBSurface *bufferSurface = data->buffers[frame->buf];
00681 if (!bufferSurface)
00682 return;
00683
00684 if (data->has_blit)
00685 {
00686 fberr = data->videoSurface->Blit(
00687 data->videoSurface, bufferSurface, NULL, 0, 0);
00688
00689 if (fberr)
00690 VERBOSE(VB_IMPORTANT, LOC_ERR + "Blit failed" + ENOFB);
00691
00692 return;
00693 }
00694
00695 void *vsrc = NULL, *vdst = NULL;
00696 int y_src_pitch = 0, y_dst_pitch = 0;
00697
00698 fberr = bufferSurface->Lock(
00699 bufferSurface, DSLF_READ, &vsrc, &y_src_pitch);
00700
00701 if (DFB_OK != fberr)
00702 {
00703 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to lock buf surf" + ENOFB);
00704 return;
00705 }
00706
00707 fberr = data->videoSurface->Lock(
00708 data->videoSurface, DSLF_WRITE, &vdst, &y_dst_pitch);
00709
00710 if (DFB_OK != fberr)
00711 {
00712 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to lock video surf" + ENOFB);
00713
00714 fberr = bufferSurface->Unlock(bufferSurface);
00715 if (DFB_OK != fberr)
00716 {
00717 VERBOSE(VB_IMPORTANT, LOC_ERR +
00718 "Failed to unlock buf surf" + ENOFB);
00719 }
00720
00721 return;
00722 }
00723
00724 unsigned char *src = (unsigned char*) vsrc;
00725 unsigned char *dst = (unsigned char*) vdst;
00726
00727 DFBSurfacePixelFormat fmt;
00728 data->videoSurface->GetPixelFormat(data->videoSurface, &fmt);
00729
00730 int pitches[3];
00731 pitches[0] = y_dst_pitch;
00732 pitches[1] = pitches[2] = (y_dst_pitch>>1);
00733
00734 int offsets[3] = { 0, 0, 0, };
00735 if (DSPF_YV12 == fmt)
00736 {
00737 offsets[1] = offsets[0] + pitches[0] * frame->height;
00738 offsets[2] = offsets[1] + pitches[1] * (frame->height>>1);
00739 }
00740 else if (DSPF_I420 == fmt)
00741 {
00742 offsets[1] = offsets[0] + pitches[0] * frame->height;
00743 offsets[2] = offsets[1] + pitches[1] * (frame->height>>1);
00744 }
00745 else
00746 {
00747 VERBOSE(VB_IMPORTANT, "Unknown Pixel Format: 0x"<<hex<<fmt<<dec);
00748 }
00749
00750 if ((DSPF_YV12 == fmt) || (DSPF_I420 == fmt))
00751 {
00752 VideoFrame src_frame;
00753 init(&src_frame, FMT_YV12, src, frame->width, frame->height,
00754 frame->bpp, frame->size, frame->pitches, frame->offsets);
00755
00756 VideoFrame dst_frame;
00757 init(&dst_frame, FMT_YV12, dst, frame->width, frame->height, 12,
00758 frame->offsets[2] + (pitches[2]>>1) * (frame->height>>1),
00759 pitches, offsets);
00760
00761 CopyFrame(&dst_frame, &src_frame);
00762
00763 #if 0
00764 cerr<<"off: "<<dst_frame.offsets[0]<<","
00765 <<dst_frame.offsets[1]<<","
00766 <<dst_frame.offsets[2]
00767 <<" p: "<<dst_frame.pitches[0]<<","
00768 <<dst_frame.pitches[1]<<","
00769 <<dst_frame.pitches[2]
00770 <<" WxH: "<<dst_frame.width<<"x"<<dst_frame.height
00771 <<" size: "<<dst_frame.size<<endl;
00772 #endif
00773
00774 #if 0
00775 memset(dst_frame.buf + dst_frame.offsets[0], 0x7f,
00776 (dst_frame.pitches[0]) * (dst_frame.height>>1));
00777
00778 bzero(dst_frame.buf + dst_frame.offsets[1],
00779 (dst_frame.pitches[1]) * (dst_frame.height>>2));
00780
00781 bzero(dst_frame.buf + dst_frame.offsets[2],
00782 (dst_frame.pitches[2]) * (dst_frame.height>>2));
00783 #endif
00784 }
00785
00786 fberr = data->videoSurface->Unlock(data->videoSurface);
00787 if (DFB_OK != fberr)
00788 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to unlock video surf" + ENOFB);
00789
00790 fberr = bufferSurface->Unlock(bufferSurface);
00791 if (DFB_OK != fberr)
00792 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to unlock buf surf" + ENOFB);
00793 }
00794
00795 void VideoOutputDirectfb::Show(FrameScanType)
00796 {
00797 DFBResult fberr = DFB_OK;
00798
00799 fberr = data->videoSurface->Flip(data->videoSurface, NULL, DSFLIP_ONSYNC);
00800
00801 DFBInputEvent event;
00802 fberr = data->inputbuf->GetEvent(data->inputbuf, DFB_EVENT(&event));
00803
00804 if (DFB_OK != fberr)
00805 return;
00806
00807 QMap<uint,QtKey>::const_iterator it = data->qtKeyMap.find(event.key_id);
00808 if (it == data->qtKeyMap.end())
00809 return;
00810
00811 QtKey key = *it;
00812 QKeyEvent *keyevent = NULL;
00813
00814 if (event.type == DIET_KEYPRESS)
00815 keyevent = new QKeyEvent(QEvent::KeyPress, key.key, key.ascii, 0);
00816 else if (event.type == DIET_KEYRELEASE)
00817 keyevent = new QKeyEvent(QEvent::KeyRelease, key.key, key.ascii, 0);
00818
00819 if (keyevent)
00820 QApplication::postEvent(widget, keyevent);
00821 }
00822
00823 void VideoOutputDirectfb::UpdatePauseFrame(void)
00824 {
00825 VideoFrame *used_frame = vbuffers.head(kVideoBuffer_used);
00826 if (!used_frame)
00827 used_frame = vbuffers.GetScratchFrame();
00828
00829
00830 IDirectFBSurface *bufferSurface = data->buffers[used_frame->buf];
00831 if (!bufferSurface)
00832 return;
00833
00834 void *vsrc = NULL;
00835 int y_src_pitch = 0;
00836 DFBResult fberr = bufferSurface->Lock(
00837 bufferSurface, DSLF_READ, &vsrc, &y_src_pitch);
00838 if (DFB_OK != fberr)
00839 {
00840 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to lock scratch surf" + ENOFB);
00841 return;
00842 }
00843
00844 unsigned char *src = (unsigned char*) vsrc;
00845
00846 VideoFrame src_frame;
00847 init(&src_frame, FMT_YV12, src,
00848 used_frame->width, used_frame->height, used_frame->bpp,
00849 used_frame->size, used_frame->pitches, used_frame->offsets);
00850
00851 CopyFrame(&pauseFrame, &src_frame);
00852
00853 fberr = bufferSurface->Unlock(bufferSurface);
00854 if (DFB_OK != fberr)
00855 {
00856 VERBOSE(VB_IMPORTANT, LOC_ERR +
00857 "Failed to unlock scratch surf" + ENOFB);
00858 }
00859 }
00860
00861 void VideoOutputDirectfb::ProcessFrame(VideoFrame *frame, OSD *osd,
00862 FilterChain *filterList,
00863 NuppelVideoPlayer *pipPlayer)
00864 {
00865 bool copy_from_pause = false;
00866 if (!frame)
00867 {
00868 frame = vbuffers.GetScratchFrame();
00869 copy_from_pause = true;
00870 }
00871
00872 IDirectFBSurface *bufferSurface = data->buffers[frame->buf];
00873 if (!bufferSurface)
00874 return;
00875
00876 void *vsrc = NULL;
00877 int y_src_pitch = 0;
00878 DFBResult fberr = bufferSurface->Lock(
00879 bufferSurface, DSLF_READ, &vsrc, &y_src_pitch);
00880 if (DFB_OK != fberr)
00881 {
00882 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to lock process surf" + ENOFB);
00883 return;
00884 }
00885
00886 unsigned char *src = (unsigned char*) vsrc;
00887
00888 VideoFrame mem_frame;
00889 init(&mem_frame, FMT_YV12, src,
00890 frame->width, frame->height, frame->bpp,
00891 frame->size, frame->pitches, frame->offsets);
00892
00893 if (copy_from_pause)
00894 CopyFrame(&mem_frame, &pauseFrame);
00895
00896 if (m_deinterlacing && m_deintFilter != NULL)
00897 m_deintFilter->ProcessFrame(&mem_frame);
00898
00899 if (filterList)
00900 filterList->ProcessFrame(&mem_frame);
00901
00902 ShowPip(&mem_frame, pipPlayer);
00903 DisplayOSD(&mem_frame, osd);
00904
00905 fberr = bufferSurface->Unlock(bufferSurface);
00906 if (DFB_OK != fberr)
00907 {
00908 VERBOSE(VB_IMPORTANT, LOC_ERR +
00909 "Failed to unlock process surf" + ENOFB);
00910 }
00911 }
00912
00913 bool VideoOutputDirectfb::InputChanged(const QSize &input_size,
00914 float aspect,
00915 MythCodecID av_codec_id,
00916 void *codec_private)
00917 {
00918 VideoOutput::InputChanged(input_size, aspect, av_codec_id, codec_private);
00919
00920 DFBSurfaceDescription desc;
00921 bzero(&desc, sizeof(DFBSurfaceDescription));
00922
00923 desc.flags = (DFBSurfaceDescriptionFlags)
00924 (DSDESC_HEIGHT | DSDESC_WIDTH | DSDESC_PIXELFORMAT);
00925 desc.width = video_dim.width();
00926 desc.height = video_dim.height();
00927 desc.pixelformat = data->videoLayerConfig.pixelformat;
00928
00929 data->DeleteBuffers(vbuffers);
00930 data->CreateBuffers(vbuffers, desc);
00931 MoveResize();
00932
00933 if (pauseFrame.buf)
00934 {
00935 delete [] pauseFrame.buf;
00936 pauseFrame.buf = NULL;
00937 }
00938
00939 init(&pauseFrame, vbuffers.GetScratchFrame()->codec,
00940 new unsigned char[vbuffers.GetScratchFrame()->size + 64],
00941 vbuffers.GetScratchFrame()->width,
00942 vbuffers.GetScratchFrame()->height,
00943 vbuffers.GetScratchFrame()->bpp,
00944 vbuffers.GetScratchFrame()->size);
00945
00946 pauseFrame.frameNumber = vbuffers.GetScratchFrame()->frameNumber;
00947
00948 return true;
00949 }
00950
00951
00952 void VideoOutputDirectfb::Zoom(ZoomDirection direction)
00953 {
00954 VideoOutput::Zoom(direction);
00955 MoveResize();
00956 }
00957
00958 void VideoOutputDirectfb::MoveResize(void)
00959 {
00960 VideoOutput::MoveResize();
00961
00962 VERBOSE(VB_PLAYBACK, LOC +
00963 QString("MoveResize : screen size %1x%2, "
00964 "proposed x : %3, y : %4, w : %5, h : %6")
00965 .arg(display_visible_rect.width())
00966 .arg(display_visible_rect.height())
00967 .arg(display_video_rect.left())
00968 .arg(display_video_rect.top())
00969 .arg(display_video_rect.width())
00970 .arg(display_video_rect.height()));
00971
00972
00973
00974
00975 if (data->videoLayerDesc.caps & DLCAPS_SCREEN_LOCATION)
00976 {
00977 float dispxoff = display_video_rect.left();
00978 float dispyoff = display_video_rect.top();
00979 float dispwoff = display_video_rect.width();
00980 float disphoff = display_video_rect.height();
00981
00982 DFBResult fberr = data->videoLayer->SetScreenLocation(
00983 data->videoLayer,
00984 dispxoff / display_visible_rect.width(),
00985 dispyoff / display_visible_rect.height(),
00986 dispwoff / display_visible_rect.width(),
00987 disphoff/display_visible_rect.height());
00988
00989 if (fberr)
00990 {
00991 VERBOSE(VB_IMPORTANT, LOC_WARN + "MoveResize" + ENOFB);
00992 }
00993 }
00994 }
00995
00996
00997 int VideoOutputDirectfb::SetPictureAttribute(
00998 PictureAttribute attribute, int newValue)
00999 {
01000 DFBColorAdjustment adj = { DCAF_NONE, 0x8000, 0x8000, 0x8000, 0x8000, };
01001
01002 data->videoLayer->GetColorAdjustment(data->videoLayer, &adj);
01003 adj.flags = DCAF_NONE;
01004
01005 newValue = min(max(newValue, 0), 100);
01006 uint value = (0xffff * newValue) / 100;
01007
01008 if ((kPictureAttribute_Brightness == attribute) &&
01009 (data->videoLayerDesc.caps & DLCAPS_BRIGHTNESS))
01010 {
01011 adj.flags = DCAF_BRIGHTNESS;
01012 adj.brightness = value;
01013 }
01014 else if ((kPictureAttribute_Contrast == attribute) &&
01015 (data->videoLayerDesc.caps & DLCAPS_CONTRAST))
01016 {
01017 adj.flags = DCAF_CONTRAST;
01018 adj.contrast = value;
01019 }
01020 else if ((kPictureAttribute_Colour == attribute) &&
01021 (data->videoLayerDesc.caps & DLCAPS_SATURATION))
01022 {
01023 adj.flags = DCAF_SATURATION;
01024 adj.saturation = value;
01025 }
01026 else if ((kPictureAttribute_Hue == attribute) &&
01027 (data->videoLayerDesc.caps & DLCAPS_HUE))
01028 {
01029 adj.flags = DCAF_HUE;
01030 adj.hue = value;
01031 }
01032
01033 if (adj.flags)
01034 {
01035 data->videoLayer->SetColorAdjustment(data->videoLayer,
01036 (DFBColorAdjustment*) &adj);
01037 SetPictureAttributeDBValue(attribute, newValue);
01038 return newValue;
01039 }
01040
01041 return -1;
01042 }
01043
01044 QStringList VideoOutputDirectfb::GetAllowedRenderers(
01045 MythCodecID myth_codec_id, const QSize &video_dim)
01046 {
01047 (void) video_dim;
01048
01049 QStringList list;
01050
01051 if (myth_codec_id < kCodec_NORMAL_END)
01052 {
01053 list += "directfb";
01054 }
01055
01056 return list;
01057 }
01058
01059 DFBEnumerationResult layer_cb(
01060 unsigned int id, DFBDisplayLayerDescription desc, void *data)
01061 {
01062 struct DirectfbData *vodata = (DirectfbData*) data;
01063
01064 if (id == DLID_PRIMARY)
01065 return DFENUM_OK;
01066
01067 DFBResult fberr = vodata->dfb->GetDisplayLayer(
01068 vodata->dfb, id, &(vodata->videoLayer));
01069
01070 if (DFB_OK != fberr)
01071 {
01072 VERBOSE(VB_IMPORTANT, LOC_WARN +
01073 "Failed to get display layer" + ENOFB);
01074
01075 return DFENUM_OK;
01076 }
01077
01078 VERBOSE(VB_PLAYBACK, QString("DirectFB Layer %1 %2:")
01079 .arg(id).arg(desc.name));
01080
01081 if (desc.caps & DLCAPS_SURFACE)
01082 VERBOSE(VB_PLAYBACK, " - Has a surface.");
01083
01084 if (desc.caps & DLCAPS_ALPHACHANNEL)
01085 VERBOSE(VB_PLAYBACK, " - Supports blending based on alpha channel.");
01086
01087 if (desc.caps & DLCAPS_SRC_COLORKEY)
01088 VERBOSE(VB_PLAYBACK, " - Supports source color keying.");
01089
01090 if (desc.caps & DLCAPS_DST_COLORKEY)
01091 VERBOSE(VB_PLAYBACK, " - Supports destination color keying.");
01092
01093 if (desc.caps & DLCAPS_FLICKER_FILTERING)
01094 VERBOSE(VB_PLAYBACK, " - Supports flicker filtering.");
01095
01096 if (desc.caps & DLCAPS_DEINTERLACING)
01097 VERBOSE(VB_PLAYBACK, " - Can deinterlace.");
01098
01099 if (desc.caps & DLCAPS_OPACITY)
01100 VERBOSE(VB_PLAYBACK, " - Supports blending with global alpha.");
01101
01102 if (desc.caps & DLCAPS_SCREEN_LOCATION)
01103 VERBOSE(VB_PLAYBACK, " - Can be positioned on the screen.");
01104
01105 if (desc.caps & DLCAPS_BRIGHTNESS)
01106 VERBOSE(VB_PLAYBACK, " - Brightness can be adjusted.");
01107
01108 if (desc.caps & DLCAPS_CONTRAST)
01109 VERBOSE(VB_PLAYBACK, " - Contrast can be adjusted.");
01110
01111 if (desc.caps & DLCAPS_HUE)
01112 VERBOSE(VB_PLAYBACK, " - Hue can be adjusted.");
01113
01114 if (desc.caps & DLCAPS_SATURATION)
01115 VERBOSE(VB_PLAYBACK, " - Saturation can be adjusted.");
01116
01117 fberr = vodata->videoLayer->TestConfiguration(
01118 vodata->videoLayer, &(vodata->videoLayerConfig), NULL);
01119
01120 if (DFB_OK != fberr)
01121 {
01122 VERBOSE(VB_IMPORTANT, LOC_WARN + "Failed to test config" + ENOFB);
01123
01124 fberr = vodata->videoLayer->Release(vodata->videoLayer);
01125 if (DFB_OK != fberr)
01126 {
01127 VERBOSE(VB_IMPORTANT, LOC_ERR +
01128 "Failed to release display layer" + ENOFB);
01129 }
01130
01131 return DFENUM_OK;
01132 }
01133
01134 vodata->videoLayerDesc = desc;
01135
01136 return DFENUM_CANCEL;
01137 }
01138
01139 static void init_keymap(QMap<uint,QtKey> &qtKeyMap)
01140 {
01141 qtKeyMap[DIKI_UNKNOWN] = QtKey(0xffff, 0x00);
01142
01143 qtKeyMap[DIKI_A] = QtKey(0x41, 0x61);
01144 qtKeyMap[DIKI_B] = QtKey(0x42, 0x62);
01145 qtKeyMap[DIKI_C] = QtKey(0x43, 0x63);
01146 qtKeyMap[DIKI_D] = QtKey(0x44, 0x64);
01147 qtKeyMap[DIKI_E] = QtKey(0x45, 0x65);
01148 qtKeyMap[DIKI_F] = QtKey(0x46, 0x66);
01149 qtKeyMap[DIKI_G] = QtKey(0x47, 0x67);
01150 qtKeyMap[DIKI_H] = QtKey(0x48, 0x68);
01151 qtKeyMap[DIKI_I] = QtKey(0x49, 0x69);
01152 qtKeyMap[DIKI_J] = QtKey(0x4a, 0x6a);
01153 qtKeyMap[DIKI_K] = QtKey(0x4b, 0x8b);
01154 qtKeyMap[DIKI_L] = QtKey(0x4c, 0x6c);
01155 qtKeyMap[DIKI_M] = QtKey(0x4d, 0x6d);
01156 qtKeyMap[DIKI_N] = QtKey(0x4e, 0x6e);
01157 qtKeyMap[DIKI_O] = QtKey(0x4f, 0x6f);
01158 qtKeyMap[DIKI_P] = QtKey(0x50, 0x70);
01159 qtKeyMap[DIKI_Q] = QtKey(0x51, 0x71);
01160 qtKeyMap[DIKI_R] = QtKey(0x52, 0x72);
01161 qtKeyMap[DIKI_S] = QtKey(0x53, 0x73);
01162 qtKeyMap[DIKI_T] = QtKey(0x54, 0x74);
01163 qtKeyMap[DIKI_U] = QtKey(0x55, 0x75);
01164 qtKeyMap[DIKI_V] = QtKey(0x56, 0x76);
01165 qtKeyMap[DIKI_W] = QtKey(0x57, 0x77);
01166 qtKeyMap[DIKI_X] = QtKey(0x58, 0x78);
01167 qtKeyMap[DIKI_Y] = QtKey(0x59, 0x79);
01168 qtKeyMap[DIKI_Z] = QtKey(0x5a, 0x7a);
01169
01170 qtKeyMap[DIKI_0] = QtKey(0x30, 0x30);
01171 qtKeyMap[DIKI_1] = QtKey(0x31, 0x31);
01172 qtKeyMap[DIKI_2] = QtKey(0x32, 0x32);
01173 qtKeyMap[DIKI_3] = QtKey(0x33, 0x33);
01174 qtKeyMap[DIKI_4] = QtKey(0x34, 0x34);
01175 qtKeyMap[DIKI_5] = QtKey(0x35, 0x35);
01176 qtKeyMap[DIKI_6] = QtKey(0x36, 0x36);
01177 qtKeyMap[DIKI_7] = QtKey(0x37, 0x37);
01178 qtKeyMap[DIKI_8] = QtKey(0x38, 0x38);
01179 qtKeyMap[DIKI_9] = QtKey(0x39, 0x39);
01180
01181 qtKeyMap[DIKI_F1] = QtKey(0x1030, 0x00);
01182 qtKeyMap[DIKI_F2] = QtKey(0x1031, 0x00);
01183 qtKeyMap[DIKI_F3] = QtKey(0x1032, 0x00);
01184 qtKeyMap[DIKI_F4] = QtKey(0x1033, 0x00);
01185 qtKeyMap[DIKI_F5] = QtKey(0x1034, 0x00);
01186 qtKeyMap[DIKI_F6] = QtKey(0x1035, 0x00);
01187 qtKeyMap[DIKI_F7] = QtKey(0x1036, 0x00);
01188 qtKeyMap[DIKI_F8] = QtKey(0x1037, 0x00);
01189 qtKeyMap[DIKI_F9] = QtKey(0x1038, 0x00);
01190 qtKeyMap[DIKI_F10] = QtKey(0x1039, 0x00);
01191 qtKeyMap[DIKI_F11] = QtKey(0x103a, 0x00);
01192 qtKeyMap[DIKI_F12] = QtKey(0x103b, 0x00);
01193
01194 qtKeyMap[DIKI_SHIFT_L] = QtKey(0x1020, 0x00);
01195 qtKeyMap[DIKI_SHIFT_R] = QtKey(0x1020, 0x00);
01196 qtKeyMap[DIKI_CONTROL_L] = QtKey(0x1021, 0x00);
01197 qtKeyMap[DIKI_CONTROL_R] = QtKey(0x1021, 0x00);
01198 qtKeyMap[DIKI_ALT_L] = QtKey(0x1023, 0x00);
01199 qtKeyMap[DIKI_ALT_R] = QtKey(0x1023, 0x00);
01200 qtKeyMap[DIKI_META_L] = QtKey(0x1022, 0x00);
01201 qtKeyMap[DIKI_META_R] = QtKey(0x1022, 0x00);
01202 qtKeyMap[DIKI_SUPER_L] = QtKey(0x1053, 0x00);
01203 qtKeyMap[DIKI_SUPER_R] = QtKey(0x1054, 0x00);
01204 qtKeyMap[DIKI_HYPER_L] = QtKey(0x1056, 0x00);
01205 qtKeyMap[DIKI_HYPER_R] = QtKey(0x1057, 0x00);
01206
01207 qtKeyMap[DIKI_CAPS_LOCK] = QtKey(0x1024, 0x00);
01208 qtKeyMap[DIKI_NUM_LOCK] = QtKey(0x1025, 0x00);
01209 qtKeyMap[DIKI_SCROLL_LOCK]= QtKey(0x1026, 0x00);
01210
01211 qtKeyMap[DIKI_ESCAPE] = QtKey(0x1000, 0x1b);
01212 qtKeyMap[DIKI_LEFT] = QtKey(0x1012, 0x00);
01213 qtKeyMap[DIKI_RIGHT] = QtKey(0x1014, 0x00);
01214 qtKeyMap[DIKI_UP] = QtKey(0x1013, 0x00);
01215 qtKeyMap[DIKI_DOWN] = QtKey(0x1015, 0x00);
01216 qtKeyMap[DIKI_TAB] = QtKey(0x1001, 0x09);
01217 qtKeyMap[DIKI_ENTER] = QtKey(0x1004, 0x0d);
01218 qtKeyMap[DIKI_SPACE] = QtKey(0x20, 0x20);
01219 qtKeyMap[DIKI_BACKSPACE] = QtKey(0x1003, 0x00);
01220 qtKeyMap[DIKI_INSERT] = QtKey(0x1006, 0x00);
01221 qtKeyMap[DIKI_DELETE] = QtKey(0x1007, 0x7f);
01222 qtKeyMap[DIKI_HOME] = QtKey(0x1010, 0x00);
01223 qtKeyMap[DIKI_END] = QtKey(0x1011, 0x00);
01224 qtKeyMap[DIKI_PAGE_UP] = QtKey(0x1016, 0x00);
01225 qtKeyMap[DIKI_PAGE_DOWN] = QtKey(0x1017, 0x00);
01226 qtKeyMap[DIKI_PRINT] = QtKey(0x1009, 0x00);
01227 qtKeyMap[DIKI_PAUSE] = QtKey(0x1008, 0x00);
01228
01229 qtKeyMap[DIKI_QUOTE_LEFT] = QtKey(0x60, 0x27);
01230 qtKeyMap[DIKI_MINUS_SIGN] = QtKey(0x2d, 0x2d);
01231 qtKeyMap[DIKI_EQUALS_SIGN]= QtKey(0x3d, 0x3d);
01232 qtKeyMap[DIKI_BRACKET_LEFT]=QtKey(0x5b, 0x5b);
01233 qtKeyMap[DIKI_BRACKET_RIGHT]=QtKey(0x5d, 0x5d);
01234 qtKeyMap[DIKI_BACKSLASH] = QtKey(0x5c, 0x5c);
01235 qtKeyMap[DIKI_SEMICOLON] = QtKey(0x3b, 0x3b);
01236
01237 qtKeyMap[DIKI_COMMA] = QtKey(0x2c, 0x2c);
01238 qtKeyMap[DIKI_PERIOD] = QtKey(0x2e, 0x2e);
01239 qtKeyMap[DIKI_SLASH] = QtKey(0x2f, 0x2f);
01240
01241 qtKeyMap[DIKI_LESS_SIGN] = QtKey(0x3c, 0x3c);
01242
01243
01244
01245 qtKeyMap[DIKI_KP_DIV] = QtKey(0xf7, '/');
01246 qtKeyMap[DIKI_KP_MULT] = QtKey(0xd7, '*');
01247 qtKeyMap[DIKI_KP_MINUS] = QtKey(0x2d, '-');
01248 qtKeyMap[DIKI_KP_PLUS] = QtKey(0x2b, '+');
01249 qtKeyMap[DIKI_KP_ENTER] = QtKey(0x1004, '\r');
01250 qtKeyMap[DIKI_KP_SPACE] = QtKey(0x20, ' ');
01251 qtKeyMap[DIKI_KP_TAB] = QtKey(0x1001, '\t');
01252 qtKeyMap[DIKI_KP_F1] = QtKey(0x1030, 0x00);
01253 qtKeyMap[DIKI_KP_F2] = QtKey(0x1031, 0x00);
01254 qtKeyMap[DIKI_KP_F3] = QtKey(0x1032, 0x00);
01255 qtKeyMap[DIKI_KP_F4] = QtKey(0x1033, 0x00);
01256 qtKeyMap[DIKI_KP_EQUAL] = QtKey(0x3d, '=');
01257
01258
01259
01260
01261 qtKeyMap[DIKI_KP_0] = QtKey(0x30, 0x30);
01262 qtKeyMap[DIKI_KP_1] = QtKey(0x31, 0x31);
01263 qtKeyMap[DIKI_KP_2] = QtKey(0x32, 0x32);
01264 qtKeyMap[DIKI_KP_3] = QtKey(0x33, 0x33);
01265 qtKeyMap[DIKI_KP_4] = QtKey(0x34, 0x34);
01266 qtKeyMap[DIKI_KP_5] = QtKey(0x35, 0x35);
01267 qtKeyMap[DIKI_KP_6] = QtKey(0x36, 0x36);
01268 qtKeyMap[DIKI_KP_7] = QtKey(0x37, 0x37);
01269 qtKeyMap[DIKI_KP_8] = QtKey(0x38, 0x38);
01270 qtKeyMap[DIKI_KP_9] = QtKey(0x39, 0x39);
01271 }