summaryrefslogtreecommitdiff
path: root/src/Main.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/Main.cxx')
-rw-r--r--src/Main.cxx415
1 files changed, 415 insertions, 0 deletions
diff --git a/src/Main.cxx b/src/Main.cxx
new file mode 100644
index 0000000..10013d8
--- /dev/null
+++ b/src/Main.cxx
@@ -0,0 +1,415 @@
+namespace PluggIt {
+
+D_DEBUG_DOMAIN( PluggIt_Main, "PluggIt/Main", "PluggIt Main" );
+D_DEBUG_DOMAIN( PluggIt_View, "PluggIt/View", "PluggIt View" );
+
+class Main extends View
+{
+ class Config {
+ public DFBDimension m_size;
+ public DFBPoint m_offset;
+ public DFBDimension m_resolution;
+ public DFBSurfacePixelFormat m_format;
+ public std::string m_title;
+ public bool m_interactive;
+ public bool m_updating;
+ public bool m_use_driver;
+
+ public Config() :
+ m_format(DSPF_UNKNOWN),
+ m_interactive(false),
+ m_updating(false)
+ {
+ }
+ };
+
+
+ private Config m_config;
+ private Options m_options;
+ private Scaler m_scaler;
+
+ private IDirectFB m_dfb;
+ private IDirectFBDisplayLayer m_layer;
+ private IDirectFBWindow m_window;
+ private IDirectFBSurface m_surface;
+ private IDirectFBEventBuffer m_events;
+
+ private Source *m_source;
+
+ private DFBDimension m_source_resolution;
+
+ private DFBDimension m_view_size;
+ private DFBDimension m_view_resolution;
+ private bool m_view_visible;
+ private DFBSurfacePixelFormat m_view_format;
+
+
+ public Main() :
+ m_source(NULL),
+ m_view_visible(false)
+ {
+ D_DEBUG_AT( PluggIt_Main, "%s()\n", __FUNCTION__ );
+
+ m_options.addOption( new Options::OptionDimension( "-s", "--size", "<width>x<height>", "Size of view", m_config.m_size ) );
+ m_options.addOption( new Options::OptionPoint ( "-o", "--offset", "<x>,<y>", "Offset of view", m_config.m_offset ) );
+ m_options.addOption( new Options::OptionDimension( "-r", "--resolution", "<X>x<Y>", "Resolution of view", m_config.m_resolution ) );
+ m_options.addOption( new Options::OptionFormat ( "-f", "--format", "<pixelformat>", "Pixel format of view", m_config.m_format ) );
+ m_options.addOption( new Options::OptionString ( "-t", "--title", "<string>", "Title of window to show", m_config.m_title ) );
+ m_options.addOption( new Options::OptionBool ( "-i", "--interactive", "", "Use interactive window picking", m_config.m_interactive ) );
+ m_options.addOption( new Options::OptionBool ( "-u", "--updating", "", "Update continuously", m_config.m_updating ) );
+ m_options.addOption( new Options::OptionBool ( "-d", "--driver", "", "Use driver mode", m_config.m_use_driver ) );
+ }
+
+ public void main( int argc, char *argv[] ) {
+ D_DEBUG_AT( PluggIt_Main, "%s()\n", __FUNCTION__ );
+
+ try {
+ /* Initialize DirectFB. */
+ DirectFB::Init( &argc, &argv );
+
+ if (!m_options.parseCommandLine( argc, argv ))
+ return;
+
+ initDFB();
+ initSource();
+
+ run();
+ }
+ catch (DFBException *e) {
+ cerr << endl;
+ cerr << "Caught exception!" << endl;
+ cerr << " ==> " << e << endl;
+ }
+ catch (Exception *e) {
+ cerr << endl;
+ cerr << "Caught exception!" << endl;
+ cerr << " ==> " << e << endl;
+ }
+ }
+
+ private void initDFB() {
+ D_DEBUG_AT( PluggIt_Main, "%s()\n", __FUNCTION__ );
+
+ /* Create the super interface. */
+ m_dfb = DirectFB::Create();
+
+ m_layer = m_dfb.GetDisplayLayer( DLID_PRIMARY );
+
+ m_events = m_dfb.CreateEventBuffer();
+ }
+
+ private void initSource() {
+ D_DEBUG_AT( PluggIt_Main, "%s()\n", __FUNCTION__ );
+
+#ifdef __WIN32__
+ SourceWin32::Config config( m_config.m_interactive ?
+ SourceWin32::Config::WINDOW_SELECTION_INTERACTIVE :
+ (m_config.m_title.size() > 0 ?
+ SourceWin32::Config::WINDOW_SELECTION_TITLE :
+ SourceWin32::Config::WINDOW_SELECTION_NONE), m_config.m_title,
+ m_config.m_updating, m_config.m_use_driver );
+
+ m_source = new SourceWin32( this, config );
+#else
+ SourceX11::Config config( m_config.m_interactive ?
+ SourceX11::Config::WINDOW_SELECTION_INTERACTIVE :
+ (m_config.m_title.size() > 0 ?
+ SourceX11::Config::WINDOW_SELECTION_TITLE :
+ SourceX11::Config::WINDOW_SELECTION_NONE), m_config.m_title );
+
+ m_source = new SourceX11( this, config );
+#endif
+ }
+
+ private void run() {
+ m_source->MainLoop();
+ }
+
+ public virtual void config( DFBDimension &source_resolution ) {
+ D_DEBUG_AT( PluggIt_View, "%s( %u, %u )\n", __FUNCTION__, source_resolution.w, source_resolution.h );
+
+ /* Ignore bogus events */
+ if (m_source_resolution == source_resolution) {
+ D_DEBUG_AT( PluggIt_View, " -> unchanged source size\n" );
+ return;
+ }
+
+ m_source_resolution = source_resolution;
+
+
+ /* Calculate view resolution */
+ DFBDimension resolution = m_config.m_resolution;
+
+ if (!resolution.w) {
+ if (!resolution.h) {
+ resolution = source_resolution;
+
+ D_DEBUG_AT( PluggIt_View, " -> no width/height\n" );
+ }
+ else {
+ resolution.w = resolution.h * source_resolution.w / source_resolution.h;
+
+ D_DEBUG_AT( PluggIt_View, " -> no width\n" );
+ }
+ }
+ else if (!resolution.h) {
+ resolution.h = resolution.w * source_resolution.h / source_resolution.w;
+
+ D_DEBUG_AT( PluggIt_View, " -> no height\n" );
+ }
+
+ D_DEBUG_AT( PluggIt_View, " -> resolution %ux%u\n", resolution.w, resolution.h );
+
+
+ /* Calculate view size */
+ DFBDimension size = m_config.m_size;
+
+ if (!size.w) {
+ if (!size.h) {
+ size = resolution;
+
+ D_DEBUG_AT( PluggIt_View, " -> no width/height\n" );
+ }
+ else {
+ size.w = size.h * resolution.w / resolution.h;
+
+ D_DEBUG_AT( PluggIt_View, " -> no width\n" );
+ }
+ }
+ else if (!size.h) {
+ size.h = size.w * resolution.h / resolution.w;
+
+ D_DEBUG_AT( PluggIt_View, " -> no height\n" );
+ }
+
+ D_DEBUG_AT( PluggIt_View, " -> %ux%u\n", size.w, size.h );
+
+
+ if (m_view_resolution == resolution)
+ D_DEBUG_AT( PluggIt_View, " -> unchanged view resolution\n" );
+
+ if (m_view_size == size) {
+ D_DEBUG_AT( PluggIt_View, " -> unchanged view size\n" );
+ return;
+ }
+
+ if (m_window)
+ m_window.Resize( size.w, size.h );
+ else {
+ /* Create the window. */
+ DFBWindowDescription desc;
+
+ desc.flags = (DFBWindowDescriptionFlags)( DWDESC_POSX | DWDESC_POSY |
+ DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_PIXELFORMAT );
+ desc.posx = 0;
+ desc.posy = 0;
+ desc.width = size.w;
+ desc.height = size.h;
+ desc.pixelformat = m_config.m_format;
+
+ m_window = m_layer.CreateWindow( desc );
+
+ m_surface = m_window.GetSurface();
+
+ m_view_format = m_surface.GetPixelFormat();
+
+ m_window.AttachEventBuffer( m_events );
+ }
+
+ m_view_size = size;
+ m_view_resolution = resolution;
+
+
+ D_DEBUG_AT( PluggIt_View, " -> view size %4ux%4u\n", m_view_size.w, m_view_size.h );
+ D_DEBUG_AT( PluggIt_View, " -> view resolution %4ux%4u\n", m_view_resolution.w, m_view_resolution.h );
+ D_DEBUG_AT( PluggIt_View, " -> source resolution %4ux%4u\n", m_source_resolution.w, m_source_resolution.h );
+ }
+
+ public virtual void update( const vector<DFBRectangle_C> &rects,
+ void *ptr,
+ int pitch )
+ {
+ unsigned int i;
+ DFBRegion clip( m_view_size );
+ const DFBPoint &offset = m_config.m_offset;
+ bool first = true;
+ DFBRegion flip;
+
+ D_DEBUG_AT( PluggIt_View, "%s( [%u], %p, %d )\n", __FUNCTION__, rects.size(), ptr, pitch );
+
+ D_ASSERT( rects.size() > 0 );
+ D_ASSERT( ptr != NULL );
+
+// m_dfb.WaitIdle();
+
+ if (m_source_resolution == m_view_resolution) {
+ D_DEBUG_AT( PluggIt_View, " -> unscaled %4dx%4d\n",
+ m_source_resolution.w, m_source_resolution.h );
+
+ if (m_view_format == DSPF_RGB16) {
+ int tp = ((m_view_size.w * 2) + 7) & ~7;
+ void *tmp = malloc( tp * m_view_size.h );
+
+ for (i=0; i<rects.size(); i++) {
+ D_DEBUG_AT( PluggIt_View, " -> [%2d] %4d,%4d-%4dx%4d (original)\n",
+ i, DFB_RECTANGLE_VALS( &rects[i] ) );
+
+ DFBRegion region( DFBRectangle(rects[i]) - offset );
+
+ D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (translated)\n",
+ DFB_RECTANGLE_VALS_FROM_REGION( &region ) );
+
+ ptr = (void*)((char*) ptr + offset.x * 4 + offset.y * pitch);
+
+ /* Clip update against our resolution */
+ if (dfb_region_region_intersect( &region, &clip )) {
+ D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (clipped update)\n",
+ DFB_RECTANGLE_VALS_FROM_REGION( &region ) );
+
+ DFBRectangle rect( region );
+
+ dfb_convert_to_rgb16( DSPF_RGB32,
+ (void*)((char*) ptr + rect.x * 4 + rect.y * pitch), pitch,
+ m_view_size.h, (u16*) tmp, tp, rect.w, rect.h );
+
+ m_surface.Write( (char*) tmp + DFB_BYTES_PER_LINE( m_view_format, region.x1 ) + region.y1 * tp, tp, &rect );
+
+ if (first) {
+ first = false;
+ flip = region;
+ }
+ else
+ flip.unionWith( region );
+ //m_surface.Flip( &region );
+ }
+ }
+
+ free( tmp );
+ }
+ else {
+ for (i=0; i<rects.size(); i++) {
+ D_DEBUG_AT( PluggIt_View, " -> [%2d] %4d,%4d-%4dx%4d (original)\n",
+ i, DFB_RECTANGLE_VALS( &rects[i] ) );
+
+ DFBRegion region( DFBRectangle(rects[i]) - offset );
+
+ D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (translated)\n",
+ DFB_RECTANGLE_VALS_FROM_REGION( &region ) );
+
+ ptr = (void*)((char*) ptr + offset.x * 4 + offset.y * pitch);
+
+ /* Clip update against our resolution */
+ if (dfb_region_region_intersect( &region, &clip )) {
+ D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (clipped update)\n",
+ DFB_RECTANGLE_VALS_FROM_REGION( &region ) );
+
+ DFBRectangle rect( region );
+
+ if (m_view_format == DSPF_ARGB) {
+ u32 *p = (u32*)((char*) ptr + rect.x * 4 + rect.y * pitch);
+
+ for (int y=0; y<rect.h; y++) {
+ for (int x=0; x<rect.w; x++)
+ p[x] |= 0xff000000;
+
+ p = (u32*)((char*) p + pitch);
+ }
+ }
+
+ D_DEBUG_AT( PluggIt_View, " -> Write...\n" );
+ m_surface.Write( (char*) ptr + DFB_BYTES_PER_LINE( m_view_format, region.x1 ) + region.y1 * pitch, pitch, &rect );
+ D_DEBUG_AT( PluggIt_View, " -> Write done.\n" );
+
+ if (first) {
+ first = false;
+ flip = region;
+ }
+ else
+ flip.unionWith( region );
+ //m_surface.Flip( &region );
+ }
+ }
+ }
+ }
+ else {
+ int tp = ((m_view_size.w * 4) + 7) & ~7;
+ void *tmp = malloc( tp * m_view_size.h );
+
+ D_DEBUG_AT( PluggIt_View, " -> scaled %4dx%4d => %4dx%4d\n",
+ m_source_resolution.w, m_source_resolution.h,
+ m_view_resolution.w, m_view_resolution.h );
+
+ for (i=0; i<rects.size(); i++) {
+ D_DEBUG_AT( PluggIt_View, " -> [%2d] %4d,%4d-%4dx%4d (original)\n",
+ i, DFB_RECTANGLE_VALS( &rects[i] ) );
+
+ DFBRegion region( DFBRectangle(rects[i]) - offset );
+
+ D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (translated)\n",
+ DFB_RECTANGLE_VALS_FROM_REGION( &region ) );
+
+ ptr = (void*)((char*) ptr + offset.x * 4 + offset.y * pitch);
+
+ /* Transform source updates to view resolution */
+ region.x1 = region.x1 * m_view_resolution.w / m_source_resolution.w;
+ region.y1 = region.y1 * m_view_resolution.h / m_source_resolution.h;
+ region.x2 = region.x2 * m_view_resolution.w / m_source_resolution.w;
+ region.y2 = region.y2 * m_view_resolution.h / m_source_resolution.h;
+
+ if (region.x1 > 0)
+ region.x1--;
+
+ if (region.y1 > 0)
+ region.y1--;
+
+ if (region.x2 < m_view_resolution.w-1)
+ region.x2++;
+ if (region.x2 < m_view_resolution.w-1)
+ region.x2++;
+
+ if (region.y2 < m_view_resolution.h-1)
+ region.y2++;
+ if (region.y2 < m_view_resolution.h-1)
+ region.y2++;
+
+ D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (scaled)\n",
+ DFB_RECTANGLE_VALS_FROM_REGION( &region ) );
+
+ /* Clip update against our resolution */
+ if (dfb_region_region_intersect( &region, &clip )) {
+ D_DEBUG_AT( PluggIt_View, " -> %4d,%4d-%4dx%4d (clipped)\n",
+ DFB_RECTANGLE_VALS_FROM_REGION( &region ) );
+
+ DFBRectangle rect( region );
+
+ m_scaler.scale( m_view_format, tmp, tp, ptr, pitch,
+ m_source_resolution.w, m_source_resolution.h,
+ m_view_resolution.w, m_view_resolution.h, region );
+
+ m_surface.Write( (char*) tmp + DFB_BYTES_PER_LINE( m_view_format, region.x1 ) + region.y1 * tp, tp, &rect );
+
+ if (first) {
+ first = false;
+ flip = region;
+ }
+ else
+ flip.unionWith( region );
+ //m_surface.Flip( &region );
+ }
+ }
+
+ free( tmp );
+ }
+
+ m_surface.Flip( &flip );
+
+ if (!m_view_visible) {
+ m_window.SetOpacity( 0xff );
+
+ m_view_visible = true;
+ }
+ }
+};
+
+}
+