From f72dab3257c506fea5dc10ae0a6cc7e441bcf17c Mon Sep 17 00:00:00 2001 From: Joel Holdsworth Date: Mon, 12 May 2008 13:02:14 +0100 Subject: [PATCH] Added support for video via a GDK fallback --- src/gui/src/Makefile.am | 2 + src/gui/src/output/displayer.cpp | 22 +++--- src/gui/src/output/displayer.hpp | 2 +- src/gui/src/output/gdkdisplayer.cpp | 76 ++++++++++++++++++++ src/gui/src/output/gdkdisplayer.hpp | 62 ++++++++++++++++ src/gui/src/output/xvdisplayer.cpp | 13 ++-- src/gui/src/output/xvdisplayer.hpp | 3 +- src/gui/src/widgets/video-display-widget.cpp | 37 ++++++++-- src/gui/src/widgets/video-display-widget.hpp | 10 ++- 9 files changed, 198 insertions(+), 29 deletions(-) create mode 100644 src/gui/src/output/gdkdisplayer.cpp create mode 100644 src/gui/src/output/gdkdisplayer.hpp diff --git a/src/gui/src/Makefile.am b/src/gui/src/Makefile.am index 29e6a6cfb..455dcdd60 100644 --- a/src/gui/src/Makefile.am +++ b/src/gui/src/Makefile.am @@ -41,6 +41,8 @@ gtk_lumiera_SOURCES = \ model/project.hpp \ output/displayer.cpp \ output/displayer.hpp \ + output/gdkdisplayer.cpp \ + output/gdkdisplayer.hpp \ output/xvdisplayer.cpp \ output/xvdisplayer.hpp diff --git a/src/gui/src/output/displayer.cpp b/src/gui/src/output/displayer.cpp index 359d0aaa3..567bc8748 100644 --- a/src/gui/src/output/displayer.cpp +++ b/src/gui/src/output/displayer.cpp @@ -23,6 +23,8 @@ * *****************************************************/ #include "displayer.hpp" +#include "xvdisplayer.hpp" +#include "gdkdisplayer.hpp" namespace lumiera { namespace gui { @@ -31,7 +33,7 @@ namespace output { bool Displayer::usable() { - return false; + return false; } DisplayerInput @@ -53,19 +55,19 @@ Displayer::preferredHeight() } void -Displayer::CalculateVideoLayout( +Displayer::calculateVideoLayout( int widget_width, int widget_height, int image_width, int image_height, int &video_x, int &video_y, int &video_width, int &video_height ) { - double ratio_width = ( double ) widget_width / ( double ) image_width; - double ratio_height = ( double ) widget_height / ( double ) image_height; - double ratio_constant = ratio_height < ratio_width ? - ratio_height : ratio_width; - video_width = ( int ) ( image_width * ratio_constant + 0.5 ); - video_height = ( int ) ( image_height * ratio_constant + 0.5 ); - video_x = ( widget_width - video_width ) / 2; - video_y = ( widget_height - video_height ) / 2; + double ratio_width = ( double ) widget_width / ( double ) image_width; + double ratio_height = ( double ) widget_height / ( double ) image_height; + double ratio_constant = ratio_height < ratio_width ? + ratio_height : ratio_width; + video_width = ( int ) ( image_width * ratio_constant + 0.5 ); + video_height = ( int ) ( image_height * ratio_constant + 0.5 ); + video_x = ( widget_width - video_width ) / 2; + video_y = ( widget_height - video_height ) / 2; } } // namespace output diff --git a/src/gui/src/output/displayer.hpp b/src/gui/src/output/displayer.hpp index 2d568607e..c117d5cb9 100644 --- a/src/gui/src/output/displayer.hpp +++ b/src/gui/src/output/displayer.hpp @@ -99,7 +99,7 @@ namespace output { protected: - static void CalculateVideoLayout( + static void calculateVideoLayout( int widget_width, int widget_height, int image_width, int image_height, int &video_x, int &video_y, int &video_width, int &video_height ); diff --git a/src/gui/src/output/gdkdisplayer.cpp b/src/gui/src/output/gdkdisplayer.cpp new file mode 100644 index 000000000..262d28d5b --- /dev/null +++ b/src/gui/src/output/gdkdisplayer.cpp @@ -0,0 +1,76 @@ +/* + gdkdisplayer.cpp - Implements the class for displaying video via GDK + + Copyright (C) Lumiera.org + 2000, Arne Schirmacher + 2001-2007, Dan Dennedy + 2008, Joel Holdsworth + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +using std::cerr; +using std::endl; + +#include "gdkdisplayer.hpp" + +namespace lumiera { +namespace gui { +namespace output { + +GdkDisplayer::GdkDisplayer( Gtk::Widget *drawing_area, int width, int height ) : + drawingArea( drawing_area ) +{ + imageWidth = width, imageHeight = height; +} + +bool +GdkDisplayer::usable() +{ + return true; +} + +void +GdkDisplayer::put( void *image ) +{ + int video_x = 0, video_y = 0, video_width = 0, video_height = 0; + calculateVideoLayout( + drawingArea->get_width(), + drawingArea->get_height(), + preferredWidth(), preferredHeight(), + video_x, video_y, video_width, video_height ); + + GdkWindow *window = drawingArea->get_window()->gobj(); + GdkGC *gc = gdk_gc_new( window ); + GdkPixbuf *pix = gdk_pixbuf_new_from_data( (const guchar*)image, GDK_COLORSPACE_RGB, FALSE, 8, + preferredWidth(), preferredHeight(), preferredWidth() * 3, NULL, NULL ); + GdkPixbuf *im = gdk_pixbuf_scale_simple( pix, video_width, video_height, GDK_INTERP_NEAREST ); + gdk_draw_pixbuf( window, gc, im, 0, 0, video_x, video_y, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0 ); + g_object_unref( im ); + g_object_unref( pix ); + g_object_unref( gc ); +} + +} // namespace output +} // namespace gui +} // namespace lumiera diff --git a/src/gui/src/output/gdkdisplayer.hpp b/src/gui/src/output/gdkdisplayer.hpp new file mode 100644 index 000000000..7e72fa24e --- /dev/null +++ b/src/gui/src/output/gdkdisplayer.hpp @@ -0,0 +1,62 @@ +/* + gdkdisplayer.hpp - Defines the class for displaying video via GDK + + Copyright (C) Lumiera.org + 2000, Arne Schirmacher + 2001-2007, Dan Dennedy + 2008, Joel Holdsworth + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +/** @file gdkdisplayer.hpp + ** This file contains the definition of XvDisplayer, the XVideo + ** video output implementation + ** @see gdkdisplayer.cpp + ** @see displayer.hpp + */ + +#include "displayer.hpp" + +#ifndef GDKDISPLAYER_HPP +#define GDKDISPLAYER_HPP + +namespace Gtk { + class Widget; +} + +namespace lumiera { +namespace gui { +namespace output { + + class GdkDisplayer : public Displayer + { + public: + GdkDisplayer( Gtk::Widget *drawing_area, int width, int height ); + + void put( void *image ); + + protected: + bool usable(); + + private: + Gtk::Widget *drawingArea; + }; + +} // namespace output +} // namespace gui +} // namespace lumiera + +#endif // GDKDISPLAYER_HPP diff --git a/src/gui/src/output/xvdisplayer.cpp b/src/gui/src/output/xvdisplayer.cpp index 5ca9d8c63..428decc62 100644 --- a/src/gui/src/output/xvdisplayer.cpp +++ b/src/gui/src/output/xvdisplayer.cpp @@ -1,5 +1,5 @@ /* - displayer.cpp - Implements the base class for displaying video + xvdisplayer.cpp - Implements the base class for XVideo display Copyright (C) Lumiera.org 2000, Arne Schirmacher @@ -39,16 +39,15 @@ namespace gui { namespace output { XvDisplayer::XvDisplayer( Gtk::Widget *drawing_area, int width, int height ) : - xvImage( NULL ) + xvImage( NULL ), + drawingArea( drawing_area ), + gotPort( false ) { cerr << ">> Trying XVideo at " << width << "x" << height << endl; - this->drawingArea = drawing_area; - imageWidth = width; - imageHeight = height; + imageWidth = width, imageHeight = height; shmInfo.shmaddr = NULL; - gotPort = false; Glib::RefPtr area_window = drawing_area->get_window(); @@ -215,7 +214,7 @@ XvDisplayer::put( void *image ) if(xvImage != NULL) { int video_x = 0, video_y = 0, video_width = 0, video_height = 0; - CalculateVideoLayout( + calculateVideoLayout( drawingArea->get_width(), drawingArea->get_height(), preferredWidth(), preferredHeight(), diff --git a/src/gui/src/output/xvdisplayer.hpp b/src/gui/src/output/xvdisplayer.hpp index 6daf614cf..aae4e0281 100644 --- a/src/gui/src/output/xvdisplayer.hpp +++ b/src/gui/src/output/xvdisplayer.hpp @@ -1,5 +1,5 @@ /* - xcdisplayer.hpp - Defines the base class for XVideo display + xvdisplayer.hpp - Defines the base class for XVideo display Copyright (C) Lumiera.org 2000, Arne Schirmacher @@ -25,6 +25,7 @@ ** This file contains the definition of XvDisplayer, the XVideo ** video output implementation ** @see xvdisplayer.cpp + ** @see displayer.hpp */ #include diff --git a/src/gui/src/widgets/video-display-widget.cpp b/src/gui/src/widgets/video-display-widget.cpp index 6ec626e9d..87fff7ecd 100644 --- a/src/gui/src/widgets/video-display-widget.cpp +++ b/src/gui/src/widgets/video-display-widget.cpp @@ -24,6 +24,9 @@ #include #include +#include "../output/xvdisplayer.hpp" +#include "../output/gdkdisplayer.hpp" + #include "video-display-widget.hpp" namespace lumiera { @@ -32,15 +35,15 @@ namespace widgets { VideoDisplayWidget::VideoDisplayWidget() : gdkWindow(NULL), - xvDisplayer(NULL) + displayer(NULL) { set_flags(Gtk::NO_WINDOW); } VideoDisplayWidget::~VideoDisplayWidget() { - if(xvDisplayer != NULL) - delete xvDisplayer; + if(displayer != NULL) + delete displayer; } void @@ -78,9 +81,9 @@ VideoDisplayWidget::on_realize() //make the widget receive expose events gdkWindow->set_user_data(gobj()); - if(xvDisplayer != NULL) - delete xvDisplayer; - xvDisplayer = new XvDisplayer(this, 320, 240 ); + if(displayer != NULL) + delete displayer; + displayer = createDisplayer(this, 320, 240); add_events(Gdk::ALL_EVENTS_MASK); } @@ -102,7 +105,7 @@ VideoDisplayWidget::on_button_press_event (GdkEventButton* event) for(int i = 0; i < 320*240*4; i++) buffer[i] = rand(); - xvDisplayer->put((void*)buffer); + displayer->put((void*)buffer); return true; } @@ -131,6 +134,26 @@ VideoDisplayWidget::on_expose_event(GdkEventExpose* event) return true; } +Displayer* +VideoDisplayWidget::createDisplayer( Gtk::Widget *drawingArea, int width, int height ) +{ + Displayer *displayer = NULL; + + displayer = new XvDisplayer( drawingArea, width, height ); + if ( !displayer->usable() ) + { + delete displayer; + displayer = NULL; + } + + if ( displayer == NULL ) + { + displayer = new GdkDisplayer( drawingArea, width, height ); + } + + return displayer; +} + } // namespace widgets } // namespace gui } // namespace lumiera diff --git a/src/gui/src/widgets/video-display-widget.hpp b/src/gui/src/widgets/video-display-widget.hpp index b883426ec..7a80a4b04 100644 --- a/src/gui/src/widgets/video-display-widget.hpp +++ b/src/gui/src/widgets/video-display-widget.hpp @@ -28,7 +28,7 @@ #include -#include "../output/xvdisplayer.hpp" +#include "../output/displayer.hpp" using namespace lumiera::gui::output; @@ -51,13 +51,17 @@ namespace widgets { virtual bool on_expose_event(GdkEventExpose* event); -virtual bool on_button_press_event (GdkEventButton* event); + virtual bool on_button_press_event (GdkEventButton* event); /* ===== Internals ===== */ + private: + static Displayer* + createDisplayer( Gtk::Widget *drawingArea, int width, int height ); + private: Glib::RefPtr gdkWindow; - XvDisplayer *xvDisplayer; + Displayer *displayer; }; } // namespace widgets