1 /*****************************************************************************
2 * vout_beos.cpp: beos video output display method
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: vout_beos.cpp,v 1.46 2002/03/17 05:48:18 tcastley 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 * Modify Refresh : code to detect refresh changes
101 ****************************************************************************/
102 void waitForRefreshIfRequired(BScreen *screen)
105 display_mode disp_mode;
106 static uint32 refresh, oldrefresh = 0;
108 screen-> GetMode(&disp_mode);
110 (disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)*
111 (disp_mode.timing.v_total));
112 if (!(refresh == oldrefresh))
114 oldrefresh = refresh;
119 screen-> WaitForRetrace(22000);//set timeout for < 45 Hz...
123 /****************************************************************************
124 * DrawingThread : thread that really does the drawing
125 ****************************************************************************/
126 int32 Draw(void *data)
128 static float out_top, out_left, out_height, out_width;
132 screen = new BScreen();
133 p_win = (VideoWindow *) data;
135 if ( p_win-> voutWindow-> LockLooper() )
137 waitForRefreshIfRequired(screen);
140 p_win->resized = false;
141 p_win-> view-> FillRect(p_win-> voutWindow-> Bounds());
142 /* if the width is proportionally smaller */
143 if (p_win->width_scale <= p_win->height_scale)
145 out_width = p_win->i_width * p_win->width_scale;
146 out_height = p_win->i_height * p_win->width_scale;
148 if (p_win-> is_zoomed)
150 out_top = (screen-> Frame().Height() - out_height) / 2;
154 out_top = (p_win->winSize.Height() - out_height) / 2;
157 else /* if the height is proportionally smaller */
159 out_width = p_win->i_width * p_win->height_scale;
160 out_height = p_win->i_height * p_win->height_scale;
162 if (p_win-> is_zoomed)
164 out_left = (screen-> Frame().Width() - out_width) / 2;
168 out_left = (p_win->winSize.Width() - out_width) /2;
172 p_win-> view-> DrawBitmap( p_win-> bitmap[p_win-> i_buffer],
173 BRect(out_left, out_top,
174 out_left + out_width, out_top + out_height) );
175 p_win-> voutWindow-> UnlockLooper();
180 /*****************************************************************************
181 * bitmapWindow : This is the bitmap window output
182 *****************************************************************************/
183 bitmapWindow::bitmapWindow(BRect frame, VideoWindow *theOwner)
184 : BWindow( frame, NULL, B_TITLED_WINDOW,
185 B_NOT_CLOSABLE | B_NOT_MINIMIZABLE )
188 owner->winSize = frame;
189 owner->width_scale = frame.Width() / owner->i_width;
190 owner->height_scale = frame.Height() / owner->i_height;
191 owner->resized = true;
192 SetTitle(VOUT_TITLE " (BBitmap output)");
195 bitmapWindow::~bitmapWindow()
199 void bitmapWindow::FrameResized( float width, float height )
201 owner->winSize = Frame();
202 owner->width_scale = width / owner->i_width;
203 owner->height_scale = height / owner->i_height;
204 owner->resized = true;
207 void bitmapWindow::Zoom(BPoint origin, float width, float height )
209 if(owner-> is_zoomed)
211 MoveTo(owner->winSize.left, owner->winSize.top);
212 ResizeTo(owner->winSize.IntegerWidth(), owner->winSize.IntegerHeight());
213 owner->width_scale = owner->winSize.IntegerWidth() / owner->i_width;
214 owner->height_scale = owner->winSize.IntegerHeight() / owner->i_height;
215 be_app->ShowCursor();
220 screen = new BScreen(this);
221 BRect rect = screen->Frame();
224 ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
225 owner->width_scale = rect.IntegerWidth() / owner->i_width;
226 owner->height_scale = rect.IntegerHeight() / owner->i_height;
227 be_app->HideCursor();
229 owner-> is_zoomed = !owner-> is_zoomed;
230 owner->resized = true;
233 /*****************************************************************************
234 * directWindow : This is the bitmap window output
235 *****************************************************************************/
236 directWindow::directWindow(BRect frame, VideoWindow *theOwner)
237 : BDirectWindow( frame, NULL, B_TITLED_WINDOW,
238 B_NOT_CLOSABLE | B_NOT_MINIMIZABLE )
241 owner->winSize = frame;
242 owner->width_scale = frame.Width() / owner->i_width;
243 owner->height_scale = frame.Height() / owner->i_height;
244 owner->resized = true;
245 SetTitle(VOUT_TITLE " (DirectWindow output)");
248 directWindow::~directWindow()
252 void directWindow::DirectConnected(direct_buffer_info *info)
256 void directWindow::FrameResized( float width, float height )
258 owner->winSize = Frame();
259 owner->width_scale = width / owner->i_width;
260 owner->height_scale = height / owner->i_height;
261 owner->resized = true;
264 void directWindow::Zoom(BPoint origin, float width, float height )
266 if(owner-> is_zoomed)
268 SetFullScreen(false);
269 MoveTo(owner->winSize.left, owner->winSize.top);
270 ResizeTo(owner->winSize.Width(), owner->winSize.Height());
271 owner->width_scale = owner->winSize.Width() / owner->i_width;
272 owner->height_scale = owner->winSize.Height() / owner->i_height;
273 be_app->ShowCursor();
277 owner->winSize = Frame();
280 screen = new BScreen(this);
281 BRect rect = screen->Frame();
284 ResizeTo(rect.Width(), rect.Height());
285 owner->width_scale = rect.Width() / owner->i_width;
286 owner->height_scale = rect.Height() / owner->i_height;
287 be_app->HideCursor();
289 owner-> is_zoomed = !owner-> is_zoomed;
290 owner->resized = true;
293 /*****************************************************************************
294 * VideoWindow constructor and destructor
295 *****************************************************************************/
296 VideoWindow::VideoWindow( int width, int height,
297 vout_thread_t *p_video_output )
299 if ( BDirectWindow::SupportsWindowMode() )
301 voutWindow = new directWindow( BRect( 80, 50,
302 80 + width, 50 + height ), this );
306 voutWindow = new bitmapWindow( BRect( 80, 50,
307 80 + width, 50 + height ), this );
310 /* set the VideoWindow variables */
311 teardownwindow = false;
315 /* create the view to do the display */
316 view = new VLCView( voutWindow->Bounds() );
317 voutWindow->AddChild(view);
319 /* Bitmap mode overlay not available, set the system to 32bits
320 * and let BeOS do all the work */
321 bitmap[0] = new BBitmap( voutWindow->Bounds(), B_RGB32);
322 bitmap[1] = new BBitmap( voutWindow->Bounds(), B_RGB32);
323 memset(bitmap[0]->Bits(), 0, bitmap[0]->BitsLength());
324 memset(bitmap[1]->Bits(), 0, bitmap[1]->BitsLength());
326 i_width = bitmap[0]->Bounds().IntegerWidth();
327 i_height = bitmap[0]->Bounds().IntegerHeight();
329 winSize = voutWindow->Frame();
330 width_scale = winSize.Width() / i_width;
331 height_scale = winSize.Height() / i_height;
336 VideoWindow::~VideoWindow()
340 teardownwindow = true;
341 wait_for_thread(fDrawThreadID, &result);
350 void VideoWindow::drawBuffer(int bufferIndex)
354 i_buffer = bufferIndex;
356 fDrawThreadID = spawn_thread(Draw, "drawing_thread",
357 B_DISPLAY_PRIORITY, (void*) this);
358 wait_for_thread(fDrawThreadID, &status);
361 /*****************************************************************************
363 *****************************************************************************/
364 VLCView::VLCView(BRect bounds) : BView(bounds, "", B_FOLLOW_ALL, B_WILL_DRAW)
366 SetViewColor(B_TRANSPARENT_32_BIT);
369 /*****************************************************************************
371 *****************************************************************************/
376 /*****************************************************************************
378 *****************************************************************************/
379 void VLCView::MouseDown(BPoint point)
381 BWindow *win = Window();
385 /*****************************************************************************
387 *****************************************************************************/
388 void VLCView::Draw(BRect updateRect)
390 FillRect(updateRect);
397 /*****************************************************************************
399 *****************************************************************************/
400 static int vout_Create ( vout_thread_t * );
401 static int vout_Init ( vout_thread_t * );
402 static void vout_End ( vout_thread_t * );
403 static void vout_Destroy ( vout_thread_t * );
404 static int vout_Manage ( vout_thread_t * );
405 static void vout_Display ( vout_thread_t *, picture_t * );
406 static void vout_Render ( vout_thread_t *, picture_t * );
408 static int BeosOpenDisplay ( vout_thread_t *p_vout );
409 static void BeosCloseDisplay( vout_thread_t *p_vout );
411 /*****************************************************************************
412 * Functions exported as capabilities. They are declared as static so that
413 * we don't pollute the namespace too much.
414 *****************************************************************************/
415 void _M( vout_getfunctions )( function_list_t * p_function_list )
417 p_function_list->functions.vout.pf_create = vout_Create;
418 p_function_list->functions.vout.pf_init = vout_Init;
419 p_function_list->functions.vout.pf_end = vout_End;
420 p_function_list->functions.vout.pf_destroy = vout_Destroy;
421 p_function_list->functions.vout.pf_manage = vout_Manage;
422 p_function_list->functions.vout.pf_display = vout_Display;
423 p_function_list->functions.vout.pf_render = vout_Render;
426 /*****************************************************************************
427 * vout_Create: allocates BeOS video thread output method
428 *****************************************************************************
429 * This function allocates and initializes a BeOS vout method.
430 *****************************************************************************/
431 int vout_Create( vout_thread_t *p_vout )
433 /* Allocate structure */
434 p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
435 if( p_vout->p_sys == NULL )
437 intf_ErrMsg( "error: %s", strerror(ENOMEM) );
441 if( p_vout->render.i_height * p_vout->render.i_aspect
442 >= p_vout->render.i_width * VOUT_ASPECT_FACTOR )
444 p_vout->p_sys->i_width = p_vout->render.i_height
445 * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
446 p_vout->p_sys->i_height = p_vout->render.i_height;
450 p_vout->p_sys->i_width = p_vout->render.i_width;
451 p_vout->p_sys->i_height = p_vout->render.i_width
452 * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
458 /*****************************************************************************
459 * vout_Init: initialize BeOS video thread output method
460 *****************************************************************************/
461 int vout_Init( vout_thread_t *p_vout )
466 I_OUTPUTPICTURES = 0;
468 /* Open and initialize device */
469 if( BeosOpenDisplay( p_vout ) )
471 intf_ErrMsg("vout error: can't open display");
475 p_vout->p_sys->pp_buffer[0] = (u8*)p_vout->p_sys->p_window->bitmap[0]->Bits();
476 p_vout->p_sys->pp_buffer[1] = (u8*)p_vout->p_sys->p_window->bitmap[1]->Bits();
478 p_vout->output.i_width = p_vout->p_sys->i_width;
479 p_vout->output.i_height = p_vout->p_sys->i_height;
480 p_vout->output.i_aspect = p_vout->p_sys->i_width
481 * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
482 p_vout->output.i_chroma = FOURCC_RV32;
484 p_vout->output.i_rmask = 0x00ff0000;
485 p_vout->output.i_gmask = 0x0000ff00;
486 p_vout->output.i_bmask = 0x000000ff;
490 /* Find an empty picture slot */
491 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
493 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
495 p_pic = p_vout->p_picture + i_index;
505 p_vout->p_sys->i_index = 0;
506 p_pic->p->p_pixels = p_vout->p_sys->pp_buffer[0];
507 p_pic->p->i_pixel_bytes = 4;
508 p_pic->p->i_lines = p_vout->p_sys->i_height;
509 p_pic->p->b_margin = 0;
510 p_pic->p->i_pitch = 4 * p_vout->p_sys->i_width;
514 p_pic->i_status = DESTROYED_PICTURE;
515 p_pic->i_type = DIRECT_PICTURE;
517 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
524 /*****************************************************************************
525 * vout_End: terminate BeOS video thread output method
526 *****************************************************************************/
527 void vout_End( vout_thread_t *p_vout )
529 BeosCloseDisplay( p_vout );
532 /*****************************************************************************
533 * vout_Destroy: destroy BeOS video thread output method
534 *****************************************************************************
535 * Terminate an output method created by DummyCreateOutputMethod
536 *****************************************************************************/
537 void vout_Destroy( vout_thread_t *p_vout )
539 free( p_vout->p_sys );
542 /*****************************************************************************
543 * vout_Manage: handle BeOS events
544 *****************************************************************************
545 * This function should be called regularly by video output thread. It manages
546 * console events. It returns a non null value on error.
547 *****************************************************************************/
548 int vout_Manage( vout_thread_t *p_vout )
554 /*****************************************************************************
555 * vout_Render: render previously calculated output
556 *****************************************************************************/
557 void vout_Render( vout_thread_t *p_vout, picture_t *p_pic )
562 /*****************************************************************************
563 * vout_Display: displays previously rendered output
564 *****************************************************************************
565 * This function send the currently rendered image to BeOS image, waits until
566 * it is displayed and switch the two rendering buffers, preparing next frame.
567 *****************************************************************************/
568 void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
570 VideoWindow * p_win = p_vout->p_sys->p_window;
572 /* draw buffer if required */
573 if (!p_win->teardownwindow)
575 p_win->drawBuffer(p_vout->p_sys->i_index);
578 p_vout->p_sys->i_index = ++p_vout->p_sys->i_index & 1;
579 p_pic->p->p_pixels = p_vout->p_sys->pp_buffer[p_vout->p_sys->i_index];
582 /* following functions are local */
584 /*****************************************************************************
585 * BeosOpenDisplay: open and initialize BeOS device
586 *****************************************************************************/
587 static int BeosOpenDisplay( vout_thread_t *p_vout )
589 p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
590 p_vout->p_sys->i_height - 1,
593 if( p_vout->p_sys->p_window == NULL )
595 intf_ErrMsg( "error: cannot allocate memory for VideoWindow" );
602 /*****************************************************************************
603 * BeosDisplay: close and reset BeOS device
604 *****************************************************************************
605 * Returns all resources allocated by BeosOpenDisplay and restore the original
606 * state of the device.
607 *****************************************************************************/
608 static void BeosCloseDisplay( vout_thread_t *p_vout )
610 /* Destroy the video window */
611 delete p_vout->p_sys->p_window;