1 /*****************************************************************************
2 * vout_beos.cpp: beos video output display method
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: vout_beos.cpp,v 1.39 2002/02/08 15:57:29 sam Exp $
7 * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
8 * Samuel Hocevar <sam@zoy.org>
9 * Tony Castley <tcastley@mail.powerup.com.au>
10 * Richard Shepherd <richard@rshepherd.demon.co.uk>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
30 #include <errno.h> /* ENOMEM */
31 #include <stdlib.h> /* free() */
33 #include <string.h> /* strerror() */
34 #include <InterfaceKit.h>
35 #include <DirectWindow.h>
36 #include <Application.h>
41 #include <videolan/vlc.h>
44 #include "video_output.h"
46 #include "interface.h"
49 #include "VideoWindow.h"
51 #define BITS_PER_PLANE 16
52 #define BYTES_PER_PIXEL 2
54 /*****************************************************************************
55 * vout_sys_t: BeOS video output method descriptor
56 *****************************************************************************
57 * This structure is part of the video output thread descriptor.
58 * It describes the BeOS specific properties of an output thread.
59 *****************************************************************************/
60 typedef struct vout_sys_s
62 VideoWindow * p_window;
73 /*****************************************************************************
74 * beos_GetAppWindow : retrieve a BWindow pointer from the window name
75 *****************************************************************************/
76 BWindow *beos_GetAppWindow(char *name)
81 for (index = 0 ; ; index++)
83 window = be_app->WindowAt(index);
86 if (window->LockWithTimeout(20000) == B_OK)
88 if (strcmp(window->Name(), name) == 0)
99 /****************************************************************************
100 * DrawingThread : thread that really does the drawing
101 ****************************************************************************/
102 int32 Draw(void *data)
106 display_mode disp_mode;
107 static uint32 refresh, oldrefresh = 0;
109 screen = new BScreen();
110 screen-> GetMode(&disp_mode);
112 (disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)*
113 (disp_mode.timing.v_total));
114 if (!(refresh == oldrefresh))
116 intf_WarnMsg( 1, "vout info: new refreshrate is %ld:Hz", refresh );
117 oldrefresh = refresh;
120 intf_WarnMsg( 1, "vout info: enabling retrace sync" );
124 intf_WarnMsg( 1, "vout info: disabling retrace sync" );
129 p_win = (VideoWindow *) data;
130 if ( p_win-> voutWindow-> LockLooper() )
135 screen-> WaitForRetrace(22000);//set timeout for < 45 Hz...
138 p_win-> view-> DrawBitmap( p_win-> bitmap[p_win-> i_buffer],
139 p_win-> bitmap[p_win-> i_buffer]-> Bounds(),
140 p_win-> voutWindow-> Bounds() );
141 p_win-> voutWindow-> UnlockLooper();
146 /*****************************************************************************
147 * bitmapWindow : This is the bitmap window output
148 *****************************************************************************/
149 bitmapWindow::bitmapWindow(BRect frame, VideoWindow *theOwner)
150 : BWindow( frame, NULL, B_TITLED_WINDOW,
151 B_OUTLINE_RESIZE | B_NOT_CLOSABLE | B_NOT_MINIMIZABLE )
156 SetTitle(VOUT_TITLE " (BBitmap output)");
159 bitmapWindow::~bitmapWindow()
163 void bitmapWindow::FrameResized( float width, float height )
172 width_scale = width / origRect.Width();
173 height_scale = height / origRect.Height();
175 /* if the width is proportionally smaller */
176 if (width_scale <= height_scale)
178 ResizeTo(width, origRect.Height() * width_scale);
180 else /* if the height is proportionally smaller */
182 ResizeTo(origRect.Width() * height_scale, height);
186 void bitmapWindow::Zoom(BPoint origin, float width, float height )
190 MoveTo(origRect.left, origRect.top);
191 ResizeTo(origRect.IntegerWidth(), origRect.IntegerHeight());
192 be_app->ShowCursor();
197 screen = new BScreen(this);
198 BRect rect = screen->Frame();
201 ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
202 be_app->HideCursor();
204 is_zoomed = !is_zoomed;
207 /*****************************************************************************
208 * directWindow : This is the bitmap window output
209 *****************************************************************************/
210 directWindow::directWindow(BRect frame, VideoWindow *theOwner)
211 : BDirectWindow( frame, NULL, B_TITLED_WINDOW,
212 B_OUTLINE_RESIZE | B_NOT_CLOSABLE | B_NOT_MINIMIZABLE )
217 SetTitle(VOUT_TITLE " (DirectWindow output)");
220 directWindow::~directWindow()
224 void directWindow::DirectConnected(direct_buffer_info *info)
228 void directWindow::FrameResized( float width, float height )
237 width_scale = width / origRect.Width();
238 height_scale = height / origRect.Height();
240 /* if the width is proportionally smaller */
241 if (width_scale <= height_scale)
243 ResizeTo(width, origRect.Height() * width_scale);
245 else /* if the height is proportionally smaller */
247 ResizeTo(origRect.Width() * height_scale, height);
251 void directWindow::Zoom(BPoint origin, float width, float height )
255 SetFullScreen(false);
256 MoveTo(origRect.left, origRect.top);
257 ResizeTo(origRect.IntegerWidth(), origRect.IntegerHeight());
258 be_app->ShowCursor();
264 screen = new BScreen(this);
265 BRect rect = screen->Frame();
268 ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
269 be_app->HideCursor();
271 is_zoomed = !is_zoomed;
274 /*****************************************************************************
275 * VideoWindow constructor and destructor
276 *****************************************************************************/
277 VideoWindow::VideoWindow( int width, int height,
278 vout_thread_t *p_video_output )
280 if ( BDirectWindow::SupportsWindowMode() )
282 voutWindow = new directWindow( BRect( 80, 50,
283 80 + width, 50 + height ), this );
287 voutWindow = new bitmapWindow( BRect( 80, 50,
288 80 + width, 50 + height ), this );
291 /* set the VideoWindow variables */
292 teardownwindow = false;
294 /* create the view to do the display */
295 view = new VLCView( voutWindow->Bounds() );
296 voutWindow->AddChild(view);
298 /* Bitmap mode overlay not available, set the system to 32bits
299 * and let BeOS do all the work */
300 bitmap[0] = new BBitmap( voutWindow->Bounds(), B_RGB32);
301 bitmap[1] = new BBitmap( voutWindow->Bounds(), B_RGB32);
302 memset(bitmap[0]->Bits(), 0, bitmap[0]->BitsLength());
303 memset(bitmap[1]->Bits(), 0, bitmap[1]->BitsLength());
305 i_width = bitmap[0]->Bounds().IntegerWidth();
306 i_height = bitmap[0]->Bounds().IntegerHeight();
311 VideoWindow::~VideoWindow()
319 teardownwindow = true;
320 wait_for_thread(fDrawThreadID, &result);
325 void VideoWindow::resizeIfRequired( int newWidth, int newHeight )
327 if (( newWidth != i_width + 1) &&
328 ( newHeight != i_height + 1) &&
331 if ( voutWindow->Lock() )
333 view->ClearViewBitmap();
334 i_width = newWidth - 1;
335 i_height = newHeight -1;
336 voutWindow->ResizeTo((float) i_width, (float) i_height);
337 voutWindow->Unlock();
342 void VideoWindow::drawBuffer(int bufferIndex)
346 i_buffer = bufferIndex;
348 fDrawThreadID = spawn_thread(Draw, "drawing_thread",
349 B_DISPLAY_PRIORITY, (void*) this);
350 wait_for_thread(fDrawThreadID, &status);
353 /*****************************************************************************
355 *****************************************************************************/
356 VLCView::VLCView(BRect bounds) : BView(bounds, "", B_FOLLOW_ALL, B_WILL_DRAW)
358 SetViewColor(B_TRANSPARENT_32_BIT);
361 /*****************************************************************************
363 *****************************************************************************/
368 /*****************************************************************************
370 *****************************************************************************/
371 void VLCView::MouseDown(BPoint point)
373 BWindow *win = Window();
380 /*****************************************************************************
382 *****************************************************************************/
383 static int vout_Probe ( probedata_t *p_data );
384 static int vout_Create ( vout_thread_t * );
385 static int vout_Init ( vout_thread_t * );
386 static void vout_End ( vout_thread_t * );
387 static void vout_Destroy ( vout_thread_t * );
388 static int vout_Manage ( vout_thread_t * );
389 static void vout_Display ( vout_thread_t *, picture_t * );
390 static void vout_Render ( vout_thread_t *, picture_t * );
392 static int BeosOpenDisplay ( vout_thread_t *p_vout );
393 static void BeosCloseDisplay( vout_thread_t *p_vout );
395 /*****************************************************************************
396 * Functions exported as capabilities. They are declared as static so that
397 * we don't pollute the namespace too much.
398 *****************************************************************************/
399 void _M( vout_getfunctions )( function_list_t * p_function_list )
401 p_function_list->pf_probe = vout_Probe;
402 p_function_list->functions.vout.pf_create = vout_Create;
403 p_function_list->functions.vout.pf_init = vout_Init;
404 p_function_list->functions.vout.pf_end = vout_End;
405 p_function_list->functions.vout.pf_destroy = vout_Destroy;
406 p_function_list->functions.vout.pf_manage = vout_Manage;
407 p_function_list->functions.vout.pf_display = vout_Display;
408 p_function_list->functions.vout.pf_render = vout_Render;
411 /*****************************************************************************
412 * vout_Probe: probe the video driver and return a score
413 *****************************************************************************
414 * This function tries to initialize SDL and returns a score to the
415 * plugin manager so that it can select the best plugin.
416 *****************************************************************************/
417 static int vout_Probe( probedata_t *p_data )
422 /*****************************************************************************
423 * vout_Create: allocates BeOS video thread output method
424 *****************************************************************************
425 * This function allocates and initializes a BeOS vout method.
426 *****************************************************************************/
427 int vout_Create( vout_thread_t *p_vout )
429 /* Allocate structure */
430 p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
431 if( p_vout->p_sys == NULL )
433 intf_ErrMsg( "error: %s", strerror(ENOMEM) );
437 if( p_vout->render.i_height * p_vout->render.i_aspect
438 >= p_vout->render.i_width * VOUT_ASPECT_FACTOR )
440 p_vout->p_sys->i_width = p_vout->render.i_height
441 * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
442 p_vout->p_sys->i_height = p_vout->render.i_height;
446 p_vout->p_sys->i_width = p_vout->render.i_width;
447 p_vout->p_sys->i_height = p_vout->render.i_width
448 * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
451 /* Open and initialize device */
452 if( BeosOpenDisplay( p_vout ) )
454 intf_ErrMsg("vout error: can't open display");
455 free( p_vout->p_sys );
462 /*****************************************************************************
463 * vout_Init: initialize BeOS video thread output method
464 *****************************************************************************/
465 int vout_Init( vout_thread_t *p_vout )
467 VideoWindow *p_win = p_vout->p_sys->p_window;
472 I_OUTPUTPICTURES = 0;
474 p_vout->output.i_width = p_vout->p_sys->i_width;
475 p_vout->output.i_height = p_vout->p_sys->i_height;
476 p_vout->output.i_aspect = p_vout->p_sys->i_width
478 / p_vout->p_sys->i_height;
479 p_vout->output.i_chroma = FOURCC_RV32;
483 /* Find an empty picture slot */
484 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
486 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
488 p_pic = p_vout->p_picture + i_index;
498 p_vout->p_sys->i_index = 0;
499 p_pic->p->p_pixels = p_vout->p_sys->pp_buffer[0];
500 p_pic->p->i_pixel_bytes = 4;
501 p_pic->p->i_lines = p_vout->p_sys->i_height;
502 p_pic->p->b_margin = 0;
503 p_pic->p->i_pitch = 4 * p_vout->p_sys->i_width;
505 p_pic->p->i_red_mask = 0x00ff0000;
506 p_pic->p->i_green_mask = 0x0000ff00;
507 p_pic->p->i_blue_mask = 0x000000ff;
511 p_pic->i_status = DESTROYED_PICTURE;
512 p_pic->i_type = DIRECT_PICTURE;
514 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
521 /*****************************************************************************
522 * vout_End: terminate BeOS video thread output method
523 *****************************************************************************/
524 void vout_End( vout_thread_t *p_vout )
526 /* place code here to end the video */
529 /*****************************************************************************
530 * vout_Destroy: destroy BeOS video thread output method
531 *****************************************************************************
532 * Terminate an output method created by DummyCreateOutputMethod
533 *****************************************************************************/
534 void vout_Destroy( vout_thread_t *p_vout )
536 BeosCloseDisplay( p_vout );
537 free( p_vout->p_sys );
540 /*****************************************************************************
541 * vout_Manage: handle BeOS events
542 *****************************************************************************
543 * This function should be called regularly by video output thread. It manages
544 * console events. It returns a non null value on error.
545 *****************************************************************************/
546 int vout_Manage( vout_thread_t *p_vout )
548 VideoWindow * p_win = p_vout->p_sys->p_window;
550 // p_win->resizeIfRequired(p_vout->p_sys->pp_buffer[p_vout->p_sys->i_index].i_pic_width,
551 // p_vout->p_sys->pp_buffer[p_vout->p_sys->i_index].i_pic_height);
556 /*****************************************************************************
557 * vout_Render: render previously calculated output
558 *****************************************************************************/
559 void vout_Render( vout_thread_t *p_vout, picture_t *p_pic )
564 /*****************************************************************************
565 * vout_Display: displays previously rendered output
566 *****************************************************************************
567 * This function send the currently rendered image to BeOS image, waits until
568 * it is displayed and switch the two rendering buffers, preparing next frame.
569 *****************************************************************************/
570 void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
572 VideoWindow * p_win = p_vout->p_sys->p_window;
574 /* draw buffer if required */
575 if (!p_win->teardownwindow)
577 p_win->drawBuffer(p_vout->p_sys->i_index);
580 p_vout->p_sys->i_index = ++p_vout->p_sys->i_index & 1;
581 p_pic->p->p_pixels = p_vout->p_sys->pp_buffer[p_vout->p_sys->i_index];
584 /* following functions are local */
586 /*****************************************************************************
587 * BeosOpenDisplay: open and initialize BeOS device
588 *****************************************************************************/
589 static int BeosOpenDisplay( vout_thread_t *p_vout )
591 p_vout->p_sys->p_window = new VideoWindow(
592 main_GetIntVariable( VOUT_WIDTH_VAR, VOUT_WIDTH_DEFAULT ) + 1,
593 main_GetIntVariable( VOUT_HEIGHT_VAR, VOUT_HEIGHT_DEFAULT ) + 1,
596 if( p_vout->p_sys->p_window == NULL )
598 intf_ErrMsg( "error: cannot allocate memory for VideoWindow" );
602 p_vout->p_sys->i_width = p_vout->p_sys->p_window->i_width + 1;
603 p_vout->p_sys->i_height = p_vout->p_sys->p_window->i_height + 1;
605 p_vout->p_sys->pp_buffer[0] = (u8*)p_vout->p_sys->p_window->bitmap[0]->Bits();
606 p_vout->p_sys->pp_buffer[1] = (u8*)p_vout->p_sys->p_window->bitmap[1]->Bits();
611 /*****************************************************************************
612 * BeosDisplay: close and reset BeOS device
613 *****************************************************************************
614 * Returns all resources allocated by BeosOpenDisplay and restore the original
615 * state of the device.
616 *****************************************************************************/
617 static void BeosCloseDisplay( vout_thread_t *p_vout )
619 /* Destroy the video window */
620 delete p_vout->p_sys->p_window;