1 /*****************************************************************************
2 * vout_beos.cpp: beos video output display method
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: vout_beos.cpp,v 1.47 2002/03/20 10:33:42 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 * DrawingThread : thread that really does the drawing
101 ****************************************************************************/
102 int32 Draw(void *data)
105 p_win = (VideoWindow *) data;
107 if ( p_win-> voutWindow-> LockLooper() )
112 screen = new BScreen(p_win->voutWindow);
113 screen-> WaitForRetrace(22000);
118 p_win->resized = false;
119 p_win-> view-> FillRect(p_win-> voutWindow-> Bounds());
121 p_win-> view-> DrawBitmap( p_win-> bitmap[p_win-> i_buffer],
122 BRect(p_win->out_left, p_win->out_top,
123 p_win->out_left + p_win->out_width,
124 p_win->out_top + p_win->out_height) );
125 p_win-> voutWindow-> UnlockLooper();
130 /*****************************************************************************
131 * bitmapWindow : This is the bitmap window output
132 *****************************************************************************/
133 bitmapWindow::bitmapWindow(BRect frame, VideoWindow *theOwner)
134 : BWindow( frame, NULL, B_TITLED_WINDOW,
135 B_NOT_CLOSABLE | B_NOT_MINIMIZABLE )
138 SetTitle(VOUT_TITLE " (BBitmap output)");
141 bitmapWindow::~bitmapWindow()
145 void bitmapWindow::FrameMoved(BPoint origin)
147 owner->FrameMoved(origin);
150 void bitmapWindow::FrameResized( float width, float height )
152 owner->FrameResized(width, height);
155 void bitmapWindow::Zoom(BPoint origin, float width, float height )
157 owner->Zoom( origin, width, height );
160 void bitmapWindow::ScreenChanged(BRect frame, color_space mode)
162 owner->ScreenChanged(frame, mode);
165 void bitmapWindow::drawBuffer(int bufferIndex)
169 owner->i_buffer = bufferIndex;
170 owner->fDrawThreadID = spawn_thread(Draw, "drawing_thread",
171 B_DISPLAY_PRIORITY, (void*) owner);
172 wait_for_thread(owner->fDrawThreadID, &status);
176 /*****************************************************************************
177 * directWindow : This is the bitmap window output
178 *****************************************************************************/
179 directWindow::directWindow(BRect frame, VideoWindow *theOwner)
180 : BDirectWindow( frame, NULL, B_TITLED_WINDOW,
181 B_NOT_CLOSABLE | B_NOT_MINIMIZABLE )
184 SetTitle(VOUT_TITLE " (DirectWindow output)");
187 directWindow::~directWindow()
191 void directWindow::DirectConnected(direct_buffer_info *info)
195 void directWindow::FrameMoved(BPoint origin)
197 owner->FrameMoved(origin);
200 void directWindow::FrameResized( float width, float height )
202 owner->FrameResized(width, height);
205 void directWindow::Zoom(BPoint origin, float width, float height )
207 owner->Zoom( origin, width, height );
210 void directWindow::ScreenChanged(BRect frame, color_space mode)
212 owner->ScreenChanged(frame, mode);
215 void directWindow::drawBuffer(int bufferIndex)
219 owner->i_buffer = bufferIndex;
220 owner->fDrawThreadID = spawn_thread(Draw, "drawing_thread",
221 B_DISPLAY_PRIORITY, (void*) owner);
222 wait_for_thread(owner->fDrawThreadID, &status);
225 /*****************************************************************************
226 * VideoWindow constructor and destructor
227 *****************************************************************************/
228 VideoWindow::VideoWindow( int width, int height,
229 vout_thread_t *p_video_output )
231 if ( BDirectWindow::SupportsWindowMode() )
233 voutWindow = new directWindow( BRect( 80, 50,
234 80 + width, 50 + height ), this );
239 voutWindow = new bitmapWindow( BRect( 80, 50,
240 80 + width, 50 + height ), this );
244 /* set the VideoWindow variables */
245 teardownwindow = false;
248 /* call ScreenChanged to set vsync correctly */
250 screen = new BScreen(voutWindow);
251 ScreenChanged(screen->Frame(), screen->ColorSpace());
254 /* create the view to do the display */
255 view = new VLCView( voutWindow->Bounds() );
256 voutWindow->AddChild(view);
258 /* Bitmap mode overlay not available, set the system to 32bits
259 * and let BeOS do all the work */
260 bitmap[0] = new BBitmap( voutWindow->Bounds(), B_RGB32);
261 bitmap[1] = new BBitmap( voutWindow->Bounds(), B_RGB32);
262 memset(bitmap[0]->Bits(), 0, bitmap[0]->BitsLength());
263 memset(bitmap[1]->Bits(), 0, bitmap[1]->BitsLength());
265 i_width = bitmap[0]->Bounds().IntegerWidth();
266 i_height = bitmap[0]->Bounds().IntegerHeight();
268 winSize = voutWindow->Frame();
271 out_height = winSize.Height();
272 out_width = winSize.Width();
273 width_scale = out_width / i_width;
274 height_scale = out_height / i_height;
280 VideoWindow::~VideoWindow()
284 teardownwindow = true;
285 wait_for_thread(fDrawThreadID, &result);
294 void VideoWindow::drawBuffer(int bufferIndex)
300 directWindow *dW = (directWindow*)voutWindow;
301 dW->drawBuffer(bufferIndex);
307 bitmapWindow *bW = (bitmapWindow*)voutWindow;
308 bW->drawBuffer(bufferIndex);
314 void VideoWindow::Zoom(BPoint origin, float width, float height )
318 is_zoomed = !is_zoomed;
319 voutWindow->MoveTo(winSize.left, winSize.top);
320 voutWindow->ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
321 width_scale = winSize.IntegerWidth() / i_width;
322 height_scale = winSize.IntegerHeight() / i_height;
323 be_app->ShowCursor();
327 is_zoomed = !is_zoomed;
329 screen = new BScreen(voutWindow);
330 BRect rect = screen->Frame();
332 voutWindow->MoveTo(0,0);
333 voutWindow->ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
334 width_scale = rect.IntegerWidth() / i_width;
335 height_scale = rect.IntegerHeight() / i_height;
336 be_app->HideCursor();
341 void VideoWindow::FrameMoved(BPoint origin)
343 if (is_zoomed) return ;
344 winSize = voutWindow->Frame();
348 void VideoWindow::FrameResized( float width, float height )
350 width_scale = width / i_width;
351 height_scale = height / i_height;
352 if (width_scale <= height_scale)
354 out_width = i_width * width_scale;
355 out_height = i_height * width_scale;
357 out_top = (voutWindow->Frame().Height() - out_height) / 2;
359 else /* if the height is proportionally smaller */
361 out_width = i_width * height_scale;
362 out_height = i_height * height_scale;
364 out_left = (voutWindow->Frame().Width() - out_width) /2;
367 if (is_zoomed) return ;
368 winSize = voutWindow->Frame();
369 width_scale = width / i_width;
370 height_scale = height / i_height;
374 void VideoWindow::ScreenChanged(BRect frame, color_space mode)
379 screen = new BScreen(voutWindow);
380 display_mode disp_mode;
382 screen-> GetMode(&disp_mode);
384 (disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)*
385 (disp_mode.timing.v_total));
392 /*****************************************************************************
394 *****************************************************************************/
395 VLCView::VLCView(BRect bounds) : BView(bounds, "", B_FOLLOW_ALL, B_WILL_DRAW)
397 SetViewColor(B_TRANSPARENT_32_BIT);
400 /*****************************************************************************
402 *****************************************************************************/
407 /*****************************************************************************
409 *****************************************************************************/
410 void VLCView::MouseDown(BPoint point)
412 BWindow *win = Window();
416 /*****************************************************************************
418 *****************************************************************************/
419 void VLCView::Draw(BRect updateRect)
421 FillRect(updateRect);
428 /*****************************************************************************
430 *****************************************************************************/
431 static int vout_Create ( vout_thread_t * );
432 static int vout_Init ( vout_thread_t * );
433 static void vout_End ( vout_thread_t * );
434 static void vout_Destroy ( vout_thread_t * );
435 static int vout_Manage ( vout_thread_t * );
436 static void vout_Display ( vout_thread_t *, picture_t * );
437 static void vout_Render ( vout_thread_t *, picture_t * );
439 static int BeosOpenDisplay ( vout_thread_t *p_vout );
440 static void BeosCloseDisplay( vout_thread_t *p_vout );
442 /*****************************************************************************
443 * Functions exported as capabilities. They are declared as static so that
444 * we don't pollute the namespace too much.
445 *****************************************************************************/
446 void _M( vout_getfunctions )( function_list_t * p_function_list )
448 p_function_list->functions.vout.pf_create = vout_Create;
449 p_function_list->functions.vout.pf_init = vout_Init;
450 p_function_list->functions.vout.pf_end = vout_End;
451 p_function_list->functions.vout.pf_destroy = vout_Destroy;
452 p_function_list->functions.vout.pf_manage = vout_Manage;
453 p_function_list->functions.vout.pf_display = vout_Display;
454 p_function_list->functions.vout.pf_render = vout_Render;
457 /*****************************************************************************
458 * vout_Create: allocates BeOS video thread output method
459 *****************************************************************************
460 * This function allocates and initializes a BeOS vout method.
461 *****************************************************************************/
462 int vout_Create( vout_thread_t *p_vout )
464 /* Allocate structure */
465 p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
466 if( p_vout->p_sys == NULL )
468 intf_ErrMsg( "error: %s", strerror(ENOMEM) );
472 p_vout->p_sys->i_width = p_vout->render.i_width;
473 p_vout->p_sys->i_height = p_vout->render.i_height;
478 /*****************************************************************************
479 * vout_Init: initialize BeOS video thread output method
480 *****************************************************************************/
481 int vout_Init( vout_thread_t *p_vout )
486 I_OUTPUTPICTURES = 0;
488 /* Open and initialize device */
489 if( BeosOpenDisplay( p_vout ) )
491 intf_ErrMsg("vout error: can't open display");
494 /* Set the buffers */
495 p_vout->p_sys->pp_buffer[0] = (u8*)p_vout->p_sys->p_window->bitmap[0]->Bits();
496 p_vout->p_sys->pp_buffer[1] = (u8*)p_vout->p_sys->p_window->bitmap[1]->Bits();
498 p_vout->output.i_width = p_vout->p_sys->i_width;
499 p_vout->output.i_height = p_vout->p_sys->i_height;
500 p_vout->output.i_aspect = p_vout->p_sys->i_width
501 * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
502 p_vout->output.i_chroma = FOURCC_RV32;
504 p_vout->output.i_rmask = 0x00ff0000;
505 p_vout->output.i_gmask = 0x0000ff00;
506 p_vout->output.i_bmask = 0x000000ff;
510 /* Find an empty picture slot */
511 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
513 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
515 p_pic = p_vout->p_picture + i_index;
525 p_vout->p_sys->i_index = 0;
526 p_pic->p->p_pixels = p_vout->p_sys->pp_buffer[0];
527 p_pic->p->i_pixel_bytes = 4;
528 p_pic->p->i_lines = p_vout->p_sys->i_height;
529 p_pic->p->b_margin = 0;
530 p_pic->p->i_pitch = 4 * p_vout->p_sys->i_width;
534 p_pic->i_status = DESTROYED_PICTURE;
535 p_pic->i_type = DIRECT_PICTURE;
537 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
544 /*****************************************************************************
545 * vout_End: terminate BeOS video thread output method
546 *****************************************************************************/
547 void vout_End( vout_thread_t *p_vout )
549 BeosCloseDisplay( p_vout );
552 /*****************************************************************************
553 * vout_Destroy: destroy BeOS video thread output method
554 *****************************************************************************
555 * Terminate an output method created by DummyCreateOutputMethod
556 *****************************************************************************/
557 void vout_Destroy( vout_thread_t *p_vout )
559 free( p_vout->p_sys );
562 /*****************************************************************************
563 * vout_Manage: handle BeOS events
564 *****************************************************************************
565 * This function should be called regularly by video output thread. It manages
566 * console events. It returns a non null value on error.
567 *****************************************************************************/
568 int vout_Manage( vout_thread_t *p_vout )
574 /*****************************************************************************
575 * vout_Render: render previously calculated output
576 *****************************************************************************/
577 void vout_Render( vout_thread_t *p_vout, picture_t *p_pic )
582 /*****************************************************************************
583 * vout_Display: displays previously rendered output
584 *****************************************************************************
585 * This function send the currently rendered image to BeOS image, waits until
586 * it is displayed and switch the two rendering buffers, preparing next frame.
587 *****************************************************************************/
588 void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
590 VideoWindow * p_win = p_vout->p_sys->p_window;
592 /* draw buffer if required */
593 if (!p_win->teardownwindow)
595 p_win->drawBuffer(p_vout->p_sys->i_index);
598 p_vout->p_sys->i_index = ++p_vout->p_sys->i_index & 1;
599 p_pic->p->p_pixels = p_vout->p_sys->pp_buffer[p_vout->p_sys->i_index];
602 /* following functions are local */
604 /*****************************************************************************
605 * BeosOpenDisplay: open and initialize BeOS device
606 *****************************************************************************/
607 static int BeosOpenDisplay( vout_thread_t *p_vout )
609 p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
610 p_vout->p_sys->i_height - 1,
613 if( p_vout->p_sys->p_window == NULL )
615 intf_ErrMsg( "error: cannot allocate memory for VideoWindow" );
622 /*****************************************************************************
623 * BeosDisplay: close and reset BeOS device
624 *****************************************************************************
625 * Returns all resources allocated by BeosOpenDisplay and restore the original
626 * state of the device.
627 *****************************************************************************/
628 static void BeosCloseDisplay( vout_thread_t *p_vout )
630 /* Destroy the video window */
631 delete p_vout->p_sys->p_window;