2 Skelton for retropc emulator
4 Author : K.Ohta <whatisthis.sowhat _at_ gmail.com>
17 #include <QImageReader>
18 #include <QMutexLocker>
20 #include "qt_gldraw.h"
22 #include "menu_flags.h"
23 //#include "csp_logger.h"
25 #define REC_VIDEO_SUCCESS 1
26 #define REC_VIDEO_FULL 2
27 #define REC_VIDEO_ERROR 3
29 //extern USING_FLAGS *using_flags;
31 void OSD_BASE::set_host_window_size(int window_width, int window_height, bool window_mode)
33 if(window_width != -1) {
34 host_window_width = window_width;
36 if(window_height != -1) {
37 host_window_height = window_height;
39 host_window_mode = window_mode;
41 first_draw_screen = false;
42 first_invalidate = true;
45 void OSD_BASE::set_vm_screen_lines(int lines)
47 emit sig_resize_vm_lines(lines);
50 void OSD_BASE::set_vm_screen_size(int screen_width, int screen_height, int window_width, int window_height, int window_width_aspect, int window_height_aspect)
52 if(vm_screen_width != screen_width || vm_screen_height != screen_height) {
53 if(window_width == -1) {
54 window_width = screen_width;
56 if(window_height == -1) {
57 window_height = screen_height;
59 if(window_width_aspect == -1) {
60 window_width_aspect = window_width;
62 if(window_height_aspect == -1) {
63 window_height_aspect = window_height;
65 vm_screen_width = screen_width;
66 vm_screen_height = screen_height;
67 vm_window_width = window_width;
68 vm_window_height = window_height;
69 vm_window_width_aspect = window_width_aspect;
70 vm_window_height_aspect = window_height_aspect;
72 // change the window size
73 //emit sig_movie_set_width(screen_width);
74 //emit sig_movie_set_height(screen_height);
75 emit sig_resize_vm_screen(&(vm_screen_buffer.pImage), screen_width, screen_height);
80 scrntype_t* OSD_BASE::get_vm_screen_buffer(int y)
82 return get_buffer(&vm_screen_buffer, y);
85 scrntype_t* OSD_BASE::get_buffer(bitmap_t *p, int y)
87 if((y >= p->pImage.height()) || (y < 0) || (y >= p->height)) {
90 return (scrntype_t *)p->pImage.scanLine(y);
93 int OSD_BASE::draw_screen()
96 QMutexLocker Locker_S(screen_mutex);
97 //QMutexLocker Locker_VM(vm_mutex);
98 if(vm_screen_buffer.width != vm_screen_width || vm_screen_buffer.height != vm_screen_height) {
99 //emit sig_movie_set_width(vm_screen_width);
100 //emit sig_movie_set_height(vm_screen_height);
101 initialize_screen_buffer(&vm_screen_buffer, vm_screen_width, vm_screen_height, 0);
103 this->vm_draw_screen();
104 // screen size was changed in vm->draw_screen()
105 if(vm_screen_buffer.width != vm_screen_width || vm_screen_buffer.height != vm_screen_height) {
108 draw_screen_buffer = &vm_screen_buffer;
110 // calculate screen size
112 emit sig_update_screen(draw_screen_buffer);
114 first_draw_screen = self_invalidate = true;
117 if(now_record_video) {
123 int OSD_BASE::no_draw_screen()
125 if(now_record_video) {
131 void OSD_BASE::do_draw(bool flag)
134 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
138 frames = draw_screen();
140 frames = no_draw_screen();
142 emit sig_draw_frames(frames);
145 void OSD_BASE::update_screen()
148 // -> qt_gldraw.cpp , qt_glutil.cpp and qt_glevents.cpp within src/qt/common/ .
149 first_invalidate = self_invalidate = false;
152 void OSD_BASE::initialize_screen_buffer(bitmap_t *buffer, int width, int height, int mode)
154 release_screen_buffer(buffer);
155 buffer->width = width;
156 buffer->height = height;
157 if((width > buffer->pImage.width()) || (height > buffer->pImage.height())) {
158 QColor col(0, 0, 0, 255);
159 buffer->pImage = QImage(width, height, QImage::Format_ARGB32);
160 buffer->pImage.fill(col);
162 printf("%dx%d NULL=%d\n", buffer->pImage.width(), buffer->pImage.height(), buffer->pImage.isNull() ? 1 : 0);
164 fillcolor.setRgb(0, 0, 0, 255);
165 buffer->pImage.fill(fillcolor);
166 //emit sig_movie_set_width(width);
167 //emit sig_movie_set_height(height);
168 emit sig_resize_vm_screen(&(buffer->pImage), width, height);
171 void OSD_BASE::release_screen_buffer(bitmap_t *buffer)
173 if(!(buffer->width == 0 && buffer->height == 0)) {
174 //if(buffer->hPainter == NULL) delete buffer->hPainter;
178 //memset(buffer, 0, sizeof(bitmap_t));
182 void OSD_BASE::rotate_screen_buffer(bitmap_t *source, bitmap_t *dest)
186 void OSD_BASE::stretch_screen_buffer(bitmap_t *source, bitmap_t *dest)
190 void OSD_BASE::capture_screen()
193 char file_name[_MAX_PATH];
194 memset(file_name, 0x00, sizeof(file_name));
195 create_date_file_name((_TCHAR *)file_name, _MAX_PATH, _T("png"));
196 emit sig_save_screen((const char *)file_name);
200 bool OSD_BASE::start_record_video(int fps)
204 rec_video_fps_nsec = (int)(1.0e9 / (double)fps);
208 QDateTime nowTime = QDateTime::currentDateTime();
209 QString tmps = nowTime.toString(QString::fromUtf8("yyyy-MM-dd_hh-mm-ss.zzz."));
210 QString path = QString::fromUtf8("Saved_Movie_") + tmps + QString::fromUtf8("mp4");
211 //QString path = QString::fromUtf8("Saved_Movie_") + tmps + QString::fromUtf8("mkv");
212 path = QString::fromLocal8Bit((const char *)this->get_app_path()) + path;
213 int rate = this->get_sound_rate();
215 emit sig_save_as_movie(path, fps, rate);
216 now_record_video = true;
220 void OSD_BASE::do_start_record_video()
222 now_record_video = true;
225 void OSD_BASE::stop_record_video()
227 now_record_video = false;
228 //rec_video_nsec = 0;
229 emit sig_stop_saving_movie();
232 void OSD_BASE::restart_record_video()
234 bool tmp = now_record_video;
237 start_record_video(-1);
241 void OSD_BASE::add_extra_frames(int extra_frames)
243 //rec_video_run_frames += extra_frames;
244 rec_video_nsec += ((int)(1.0e9 / vm_frame_rate()) * extra_frames);
245 if(rec_video_nsec < 0) rec_video_nsec = 0;
246 //emit sig_send_wxita_frames(extra_frames);
250 void OSD_BASE::upload_bitmap(QImage *p)
252 if(!using_flags->is_use_one_board_computer()) return;
254 background_image = QImage(*p);
255 rec_image_buffer = QImage(*p);
259 void OSD_BASE::set_buttons()
261 if(!using_flags->is_use_one_board_computer()) return;
263 button_desc_t *vm_buttons_d = using_flags->get_vm_buttons();
264 if(vm_buttons_d != NULL) {
265 for(int i = 0; i < using_flags->get_max_button(); i++) {
267 tmps = QString::asprintf(":/button%02d.png", i);
268 QImageReader *reader = new QImageReader(tmps);
269 QImage *result = new QImage(reader->read());
272 if(!result->isNull()) {
273 pic = result->convertToFormat(QImage::Format_ARGB32);
275 pic = QImage(10, 10, QImage::Format_RGBA8888);
276 pic.fill(QColor(0,0,0,0));
280 pic = QImage(10, 10, QImage::Format_RGBA8888);
281 pic.fill(QColor(0,0,0,0));
283 button_images[i] = pic;
288 if(vm_buttons_d != NULL) {
289 for(int ii = 0; ii < using_flags->get_max_button(); ii++) {
290 int ww = button_images[ii].width();
291 int hh = button_images[ii].height();
292 for(int yy = 0; yy < hh; yy++) {
293 for(int xx = 0; xx < ww; xx++) {
294 pixel = button_images[ii].pixel(xx, yy);
295 int xxx = vm_buttons_d[ii].x + xx;
296 int yyy = vm_buttons_d[ii].y + yy;
297 background_image.setPixel(xxx, yyy, pixel);
305 int OSD_BASE::add_video_frames()
307 //static double frames = 0;
308 //static int prev_video_fps = -1;
310 //static double prev_vm_fps = -1;
311 double vm_fps = vm_frame_rate();
312 int delta_ns = (int)(1.0e9 / vm_fps);
313 //if(rec_video_fps_nsec >= delta_ns) {
314 if(delta_ns == rec_video_fps_nsec) {
315 rec_video_nsec += delta_ns;
316 if(rec_video_nsec > (rec_video_fps_nsec * 2)) {
317 rec_video_nsec -= rec_video_fps_nsec;
318 } else if(rec_video_nsec < (rec_video_fps_nsec * -2)) {
319 rec_video_nsec += rec_video_fps_nsec;
321 while(rec_video_nsec > rec_video_fps_nsec) {
322 rec_video_nsec -= rec_video_fps_nsec;
325 } else { // Will branch whether rec_video_fps_nsec >= delta_ns ?
326 rec_video_nsec += delta_ns;
327 if(rec_video_nsec > (rec_video_fps_nsec * 2)) {
328 rec_video_nsec -= rec_video_fps_nsec;
329 } else if(rec_video_nsec < (rec_video_fps_nsec * -2)) {
330 rec_video_nsec += rec_video_fps_nsec;
332 while(rec_video_nsec >= rec_video_fps_nsec) {
333 rec_video_nsec -= rec_video_fps_nsec;
338 if(using_flags->is_use_one_board_computer()) {
339 //int size = vm_screen_buffer.pImage.byteCount();
341 rec_image_buffer = QImage(background_image);
342 QImage *video_result = &(vm_screen_buffer.pImage);
344 int ww = video_result->width();
345 int hh = video_result->height();
346 //printf("%d x %d\n", ww, hh);
347 for(int yy = 0; yy < hh; yy++) {
348 for(int xx = 0; xx < ww; xx++) {
349 pixel = video_result->pixel(xx, yy);
350 #if defined(__LITTLE_ENDIAN__)
352 if(pixel != 0xff000000) {
353 rec_image_buffer.setPixel(xx, yy, pixel);
357 if(pixel != 0x000000ff) {
358 rec_image_buffer.setPixel(xx, yy, pixel);
365 emit sig_enqueue_video(i, background_image.width(), background_image.height(), &rec_image_buffer);
369 //int size = vm_screen_buffer.pImage.byteCount();
371 QImage video_result = QImage(vm_screen_buffer.pImage);
375 emit sig_enqueue_video(i, vm_screen_width, vm_screen_height, &video_result);
378 debug_log(CSP_LOG_DEBUG2, CSP_LOG_TYPE_SCREEN, "Push Video %d frames\n", counter);
385 void OSD_BASE::create_bitmap(bitmap_t *bitmap, int width, int height)
388 QColor col = QColor(0, 0, 0, 255);
389 initialize_screen_buffer(bitmap, width, height, 0); // HALFTONE
390 bitmap->hPainter.begin(&(bitmap->pImage));
391 bitmap->hPainter.fillRect(0, 0, width, height, col);
392 bitmap->hPainter.end();
393 debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Create bitmap: %08x %d x %d", bitmap, width, height);
396 void OSD_BASE::release_bitmap(bitmap_t *bitmap)
398 release_screen_buffer(bitmap);
399 debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Release bitmap: %08x", bitmap);
402 void OSD_BASE::create_font(font_t *font, const _TCHAR *family, int width, int height, int rotate, bool bold, bool italic)
405 fontName = QString::fromUtf8((const char *)family);
406 if(fontName == QString::fromUtf8("Gothic")) {
407 fontName = QString::fromUtf8("Sans Serif");
408 } else if(fontName == QString::fromUtf8("Mincho")) {
409 fontName = QString::fromUtf8("Serif");
411 //fontName = QString::fromUtf8("Sans Serif");
412 fontName = QString::fromUtf8((const char *)family);
414 font->hFont = QFont(fontName);
415 font->hFont.setPixelSize(height);
416 //font->hFont.setFixedPitch(true);
417 font->hFont.setItalic(italic);
418 font->hFont.setBold(bold);
419 QFontMetrics metric(font->hFont);
420 font->hFont.setStretch((width * 10000) / (metric.width("F") * 100));
421 font->rotate = rotate;
422 font->init_flag = true;
423 //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Create Font: Family=%s WIDTH=%d HEIGHT=%d",fontName.toUtf8().constData(), width, height);
424 // Qt uses substitution font if not found.
427 void OSD_BASE::release_font(font_t *font)
429 //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Release Font");
432 void OSD_BASE::create_pen(pen_t *pen, int width, uint8_t r, uint8_t g, uint8_t b)
438 pen->hPen = QPen(Qt::SolidLine);
439 QColor color = QColor(r, g, b, 255);
440 pen->hPen.setColor(color);
441 pen->hPen.setWidth(width);
442 //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Create PEN %08x to width=%d (RGB)=(%d,%d,%d)\n", pen, width, r, g, b);
445 void OSD_BASE::release_pen(pen_t *pen)
447 //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Release Pen %08x", pen);
450 void OSD_BASE::clear_bitmap(bitmap_t *bitmap, uint8_t r, uint8_t g, uint8_t b)
453 //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Clear bitmap %08x", bitmap);
454 draw_rectangle_to_bitmap(bitmap, 0, 0, bitmap->width, bitmap->height, r, g, b);
458 int OSD_BASE::get_text_width(bitmap_t *bitmap, font_t *font, const char *text)
460 QFontMetrics fm(font->hFont);
461 QTextCodec *codec = QTextCodec::codecForName("Shift-JIS");
462 QString s = codec->toUnicode(text);
466 void OSD_BASE::draw_text_to_bitmap(bitmap_t *bitmap, font_t *font, int x, int y, const _TCHAR *text, uint8_t r, uint8_t g, uint8_t b)
468 QColor col(r, g, b, 255);
469 QPoint loc = QPoint(x, y);
471 QTextCodec *codec = QTextCodec::codecForName("Shift-JIS");
472 QString str = codec->toUnicode((char *)text);
473 bitmap->hPainter.begin(&(bitmap->pImage));
474 //bitmap->hPainter.setBackgroundMode(Qt::OpaqueMode);
475 bitmap->hPainter.setPen(col);
476 bitmap->hPainter.rotate((qreal)font->rotate);
478 bitmap->hPainter.setFont(font->hFont);
479 bitmap->hPainter.drawText(loc, str);
480 bitmap->hPainter.end();
481 //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Draw Text to BITMAP %08x : (%d,%d) %s : Color(%d,%d,%d)", bitmap, x, y, str.toUtf8().constData(), r, g, b);
484 void OSD_BASE::draw_line_to_bitmap(bitmap_t *bitmap, pen_t *pen, int sx, int sy, int ex, int ey)
486 QLine line(sx, sy, ex, ey);
487 bitmap->hPainter.begin(&(bitmap->pImage));
488 //bitmap->hPainter.setBackgroundMode(Qt::TransparentMode);
489 bitmap->hPainter.setPen(pen->hPen);
490 bitmap->hPainter.drawLine(line);
491 bitmap->hPainter.end();
492 //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Draw Line from (%d,%d) to (%d,%d) to BITMAP %08x", sx, sy, ex, ey, bitmap);
495 void OSD_BASE::draw_point_to_bitmap(bitmap_t *bitmap, int x, int y, uint8_t r, uint8_t g, uint8_t b)
498 QColor d_col(r, g, b);
500 bitmap->hPainter.begin(&(bitmap->pImage));
501 //bitmap->hPainter.setBackgroundMode(Qt::OpaqueMode);
502 bitmap->hPainter.setPen(d_pen);
503 bitmap->hPainter.drawPoint(point);
504 bitmap->hPainter.end();
505 //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Draw Point to BITMAP %08x :(%d,%d) Color=(%d,%d,%d)", bitmap, x, y, r, g, b);
508 void OSD_BASE::draw_rectangle_to_bitmap(bitmap_t *bitmap, int x, int y, int width, int height, uint8_t r, uint8_t g, uint8_t b)
510 QColor d_col(r, g, b, 255);
511 QBrush d_brush(d_col);
512 bitmap->hPainter.begin(&(bitmap->pImage));
513 //bitmap->hPainter.setBackgroundMode(Qt::OpaqueMode);
514 bitmap->hPainter.fillRect(x, y, width, height, d_brush);
515 bitmap->hPainter.end();
516 //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Draw Rect BITMAP %08x :from (%d,%d) size=(%d,%d) Color=(%d,%d,%d)", bitmap, x, y, width, height, r, g, b);
519 void OSD_BASE::stretch_bitmap(bitmap_t *dest, int dest_x, int dest_y, int dest_width, int dest_height, bitmap_t *source, int source_x, int source_y, int source_width, int source_height)
521 QRect src_r(source_x, source_y, source_width, source_height);
522 QRect dest_r(dest_x, dest_y, dest_width, dest_height);
523 dest->hPainter.begin(&(dest->pImage));
524 //dest->hPainter.setBackgroundMode(Qt::OpaqueMode);
525 dest->hPainter.drawImage(dest_r, source->pImage, src_r);
526 dest->hPainter.end();
527 //debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Scale (%d,%d, %d, %d) to (%d,%d, %d, %d)", source_x, source_y, source_width, source_height,
528 // dest_x, dest_y, dest_width, dest_height);
533 void OSD_BASE::write_bitmap_to_file(bitmap_t *bitmap, const _TCHAR *file_path)
535 int comp_quality = 0;
536 bitmap->pImage.save(QString::fromUtf8((const char *)file_path), "PNG", comp_quality);
537 debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_PRINTER, "Save (print outed) bitmap %08x to %s", bitmap, file_path);
540 int OSD_BASE::get_vm_window_width()
542 return vm_window_width;
545 int OSD_BASE::get_vm_window_height()
547 return vm_window_height;
550 int OSD_BASE::get_vm_window_width_aspect()
552 return vm_window_width_aspect;
555 int OSD_BASE::get_vm_window_height_aspect()
557 return vm_window_height_aspect;
560 void OSD_BASE::reload_bitmap()
562 first_invalidate = true;