On Mon, Jan 06, 2003 at 03:51:46PM -0600, Billy Biggs wrote:
>   I'm more worried about whether GetCurrentOutputField() is accurate or
> not.

That's really up to the hardware. Have you had any problems?

> In tvtime I work in single buffered mode, so I never need to call
> flip.  All I do is, while the top field is being shown, draw the bottom
> field, repeat.

Would you believe I just grabbed the tvtime tarball a few days ago and
after noticing there isn't a DirectFB output driver I wrote one. I knew I
should've been using the CVS sources :) Well actually what I have is for
overlays (w/ window & colorkeying) so it's not exactly what you have in
CVS. I've attached the file in case you want to use it somehow.

-- 
Ville Syrj�l�
[EMAIL PROTECTED]
http://www.sci.fi/~syrjala/
#include "config.h"
#include "dfboutput.h"

#ifdef HAVE_DIRECTFB

#include <directfb.h>

#include "input.h"

static void *image_data;
static int image_pitch;

static IDirectFB *dfb;
static IDirectFBDisplayLayer *primary;
static IDirectFBDisplayLayer *video;
static IDirectFBWindow *window;
static IDirectFBSurface *wsurface;
static IDirectFBSurface *surface;
static IDirectFBEventBuffer *buffer;

static DFBColor colorkey = { 0xff, 0x00, 0x00, 0xff };

static int output_width, output_height;
static int input_width, input_height;
static int output_aspect = 0;
static int output_fullscreen = 0;

typedef struct {
  int x;
  int y;
  unsigned int width;
  unsigned int height;
} area_t;

area_t video_area;
static void resize_video( void )
{
     int x, y, w, h;
     
     DFBDisplayLayerConfig dlc;

     primary->GetConfiguration( primary, &dlc );

     x = video_area.x;
     y = video_area.y;
     w = video_area.width;
     h = video_area.height;
     
     if (x < 0) {
          w = w + x;
          x = 0;
     }
     if (y < 0) {
          h = h + y;
          y = 0;
     }

     if (x + w > dlc.width)
          w = dlc.width - x;
     if (y + h > dlc.height)
          h = dlc.height - y;

     video->SetScreenLocation( video,
                               (float) x / (float) dlc.width,
                               (float) y / (float) dlc.height,
                               (float) w / (float) dlc.width,
                               (float) h / (float) dlc.height );
     wsurface->Clear( wsurface, colorkey.r, colorkey.g, colorkey.b, 0xff );
     wsurface->Flip( wsurface, NULL, 0 );
}

static int open_display( void )
{
     DFBWindowDescription wd;
     DFBDisplayLayerConfig dlc;

     DirectFBCreate( &dfb );

     /* Get the primary layer */
     dfb->GetDisplayLayer( dfb, DLID_PRIMARY, &primary );
     primary->SetCooperativeLevel( primary, DLSCL_SHARED );

     /* Create a window to house the video layer */
     wd.flags = DWDESC_POSX | DWDESC_POSY | DWDESC_WIDTH | DWDESC_HEIGHT;
     wd.posx = 0;
     wd.posy = 0;
     wd.width = output_width;
     wd.height = output_height;
     primary->CreateWindow( primary, &wd, &window );

     video_area.x = 0;
     video_area.y = 0;
     video_area.width = output_width;
     video_area.height = output_height;

     window->GetSurface( window, &wsurface );

     window->SetOpacity( window, 0xff );

     /* Select events */
     window->DisableEvents( window, DWET_ALL );
     window->EnableEvents( window, DWET_BUTTONDOWN | DWET_KEYDOWN | DWET_WHEEL  | 
DWET_POSITION | DWET_SIZE );
     window->CreateEventBuffer( window, &buffer );

     /* Get the video layer */
     dfb->GetDisplayLayer( dfb, 1, &video );
     video->SetCooperativeLevel( video, DLSCL_EXCLUSIVE );

     /* Set configuration accroding to input data */
     dlc.flags = DLCONF_BUFFERMODE | DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT 
| DLCONF_OPTIONS;
     dlc.buffermode = DLBM_BACKVIDEO;
     dlc.width = input_width;
     dlc.height = input_height;
     dlc.pixelformat = DSPF_YUY2;
     dlc.options = DLOP_DST_COLORKEY;
     video->SetConfiguration( video, &dlc );

     video->SetDstColorKey( video, colorkey.r, colorkey.g, colorkey.b );

     video->SetOpacity( video, 0xff );

     return 1;
}

static void dfb_alloc_frame( void )
{
     video->GetSurface( video, &surface );
}

static void dfb_clear_screen( void )
{
     surface->Clear( surface, 0, 0, 0, 0xff );
}

int dfb_init( int inputwidth, int inputheight, int outputwidth, int aspect )
{
     output_aspect = aspect;
     input_width = inputwidth;
     input_height = inputheight;
     output_width = outputwidth;
     output_height = ( output_width * 3 ) / 4;
     open_display();
     dfb_alloc_frame();
     dfb_clear_screen();

     resize_video();

     return 1;
}

int dfb_toggle_fullscreen( int fullscreen_width, int fullscreen_height )
{
     output_fullscreen = !output_fullscreen;

     if( output_fullscreen ) {
          DFBDisplayLayerConfig dlc;

          primary->GetConfiguration( primary, &dlc );

          window->SetOptions( window,
                              DWOP_KEEP_POSITION | DWOP_KEEP_SIZE | DWOP_KEEP_STACKING 
);
          /* Raise the window to the top */
          window->RaiseToTop( window );

          /* Maximize the window */
          window->MoveTo( window, 0, 0 );
          window->Resize( window, dlc.width, dlc.height );

          window->GrabPointer( window );
          window->GrabKeyboard( window );

          /* Hide the mouse cursor */
          primary->SetCursorOpacity( primary, 0 );
     } else {
          window->SetOptions( window, DWOP_NONE );

          /* Resize the window to normal size */
          window->MoveTo( window, 0, 0 );
          window->Resize( window, output_width, output_height );

          window->UngrabPointer( window );
          window->UngrabKeyboard( window );

          /* Show the mouse cursor */
          primary->SetCursorOpacity( primary, 0xff );
     }

     return output_fullscreen;
}

int dfb_toggle_aspect( void )
{
     output_aspect = !output_aspect;
     dfb_clear_screen();
     return output_aspect;
}

void dfb_show_frame( void )
{
     surface->Flip( surface, NULL, DSFLIP_WAITFORSYNC );
}

void dfb_poll_events( input_t *in )
{
     DFBWindowEvent event;
     int arg = 0;
     int reconfigure = 0;

     while (buffer->HasEvent( buffer ) == DFB_OK) {
          if (buffer->GetEvent( buffer, DFB_EVENT( &event ) ) != DFB_OK)
               continue;

          if (event.clazz != DFEC_WINDOW)
               continue;
          
          switch( event.type ) {
          case DWET_KEYDOWN:
               if( event.modifiers & DIMM_SHIFT ) arg |= I_SHIFT;
               if( event.modifiers & DIMM_CONTROL ) arg |= I_CTRL;
               if( event.modifiers & DIMM_META ) arg |= I_META;

               if( event.key_symbol >= DIKS_SMALL_A &&
                   event.key_symbol <= DIKS_SMALL_Z ) {
                    arg |= event.key_symbol - DIKS_SMALL_A + 'a';
               } else if( event.key_symbol >= DIKS_CAPITAL_A &&
                          event.key_symbol <= DIKS_CAPITAL_Z ) {
                    arg |= event.key_symbol - DIKS_CAPITAL_A + 'a';
               } else if( event.key_symbol >= DIKS_0 &&
                          event.key_symbol <= DIKS_9 ) {
                    arg |= event.key_symbol - DIKS_0 + '0';
               }

               switch( event.key_symbol ) {
               case DIKS_ESCAPE: arg |= I_ESCAPE; break;

               case DIKS_HOME: arg |= I_HOME; break;
               case DIKS_END: arg |= I_END; break;
               case DIKS_CURSOR_LEFT: arg |= I_LEFT; break;
               case DIKS_CURSOR_UP: arg |= I_UP; break;
               case DIKS_CURSOR_RIGHT: arg |= I_RIGHT; break;
               case DIKS_CURSOR_DOWN: arg |= I_DOWN; break;
               case DIKS_PAGE_UP: arg |= I_PGUP; break;
               case DIKS_PAGE_DOWN: arg |= I_PGDN; break;

               case DIKS_F1: arg |= I_F1; break;
               case DIKS_F2: arg |= I_F2; break;
               case DIKS_F3: arg |= I_F3; break;
               case DIKS_F4: arg |= I_F4; break;
               case DIKS_F5: arg |= I_F5; break;
               case DIKS_F6: arg |= I_F6; break;
               case DIKS_F7: arg |= I_F7; break;
               case DIKS_F8: arg |= I_F8; break;
               case DIKS_F9: arg |= I_F9; break;
               case DIKS_F10: arg |= I_F10; break;
               case DIKS_F11: arg |= I_F11; break;
               case DIKS_F12: arg |= I_F12; break;

               case DIKS_ENTER: arg |= I_ENTER; break;
               case DIKS_APOSTROPHE: arg |= '*'; break;
               case DIKS_MINUS_SIGN: arg |= '-'; break;
               case DIKS_PLUS_SIGN: arg |= '+'; break;
               case DIKS_SLASH: arg |= '/'; break;

               default: break;
               }
               input_callback( in, I_KEYDOWN, arg );
               break;
          case DWET_BUTTONDOWN:
               input_callback( in, I_BUTTONPRESS, event.button );
               break;
          case DWET_WHEEL:
               input_callback( in, I_BUTTONPRESS, event.step > 0 ? 4 : 5 );
               break;
          case DWET_POSITION:
               video_area.x = event.x;
               video_area.y = event.y;
               reconfigure = 1;
               break;
          case DWET_SIZE:
               video_area.width = event.w;
               video_area.height = event.h;
               reconfigure = 1;
               break;
          default: break;
          }
     }

     if (reconfigure)
          resize_video();
}

void dfb_quit( void )
{
     /* Hide the video layer */
     video->SetOpacity( video, 0 );

     buffer->Release( buffer );
     surface->Release( surface );
     wsurface->Release( wsurface );
     window->Release( window );
     video->Release( video );
     primary->Release( primary );
     dfb->Release( dfb );
}

int dfb_get_stride( void )
{
     return image_pitch;
}

int dfb_is_interlaced( void )
{
     return 0;
}

void dfb_wait_for_sync( int field )
{
}

void dfb_lock_output( void )
{
     surface->Lock( surface, DSLF_READ | DSLF_WRITE,
                    &image_data, &image_pitch );
}

void dfb_unlock_output( void )
{
     surface->Unlock( surface );
}

void dfb_set_window_caption( const char *caption )
{
}

unsigned char *dfb_get_output( void )
{
     return image_data;
}

static output_api_t dfboutput =
{
     dfb_init,

     dfb_lock_output,
     dfb_get_output,
     dfb_get_stride,
     dfb_unlock_output,

     dfb_is_interlaced,
     dfb_wait_for_sync,
     dfb_show_frame,

     dfb_toggle_aspect,
     dfb_toggle_fullscreen,
     dfb_set_window_caption,
     
     dfb_poll_events,
     dfb_quit
};

output_api_t *get_dfb_output( void )
{
     return &dfboutput;
}

#else

output_api_t *get_dfb_output( void )
{
     return 0;
}

#endif

Reply via email to