]> git.sesse.net Git - vlc/blob - plugins/beos/vout_beos.cpp
Updated documentation
[vlc] / plugins / beos / vout_beos.cpp
1 /*****************************************************************************
2  * vout_beos.cpp: beos video output display method
3  *****************************************************************************
4  * Copyright (C) 2000, 2001 VideoLAN
5  * $Id: vout_beos.cpp,v 1.36 2001/12/30 07:09:54 sam Exp $
6  *
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>
11  *
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.
16  * 
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.
21  *
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  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <errno.h>                                                 /* ENOMEM */
31 #include <stdlib.h>                                                /* free() */
32 #include <stdio.h>
33 #include <string.h>                                            /* strerror() */
34 #include <InterfaceKit.h>
35 #include <DirectWindow.h>
36 #include <Application.h>
37 #include <Bitmap.h>
38
39 extern "C"
40 {
41 #include <videolan/vlc.h>
42
43 #include "video.h"
44 #include "video_output.h"
45
46 #include "interface.h"
47 }
48
49 #include "VideoWindow.h"
50
51 #define BITS_PER_PLANE  32
52 #define BYTES_PER_PIXEL 4
53
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
61 {
62     VideoWindow *      p_window;
63
64     byte_t *              pp_buffer[2];
65     s32                   i_width;
66     s32                   i_height;
67 } vout_sys_t;
68
69
70 /*****************************************************************************
71  * beos_GetAppWindow : retrieve a BWindow pointer from the window name
72  *****************************************************************************/
73 BWindow *beos_GetAppWindow(char *name)
74 {
75     int32       index;
76     BWindow     *window;
77     
78     for (index = 0 ; ; index++)
79     {
80         window = be_app->WindowAt(index);
81         if (window == NULL)
82             break;
83         if (window->LockWithTimeout(20000) == B_OK)
84         {
85             if (strcmp(window->Name(), name) == 0)
86             {
87                 window->Unlock();
88                 break;
89             }
90             window->Unlock();
91         }
92     }
93     return window; 
94 }
95
96 /**************************************************************************** 
97
98  * DrawingThread : thread that really does the drawing 
99  **************************************************************************** 
100 */ 
101 int32 Draw(void *data) 
102
103     //rudolf: sync init: 
104     BScreen *screen; 
105     display_mode disp_mode; 
106     static uint32 refresh, oldrefresh = 0; 
107
108     screen = new BScreen(); 
109     screen-> GetMode(&disp_mode); 
110     refresh = 
111          (disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)* 
112          (disp_mode.timing.v_total)); 
113     if (!(refresh == oldrefresh)) 
114     { 
115         printf("\nNew refreshrate is %d:Hz\n",refresh); 
116         oldrefresh = refresh; 
117         if (refresh  < 61) 
118         { 
119             printf("Enabling retrace sync.\n"); 
120         } 
121         else 
122         { 
123             printf("Disabling retrace sync.\n"); 
124         } 
125     } 
126
127     VideoWindow* p_win; 
128     p_win = (VideoWindow *) data; 
129     if ( p_win-> voutWindow-> LockLooper() ) 
130     { 
131         //rudolf: sync: 
132         if (refresh  < 61) 
133         { 
134             screen-> WaitForRetrace(22000);//set timeout for  < 45 Hz... 
135         } 
136
137         p_win-> view-> DrawBitmap( p_win-> bitmap[p_win-> i_buffer], 
138                                  p_win-> bitmap[p_win-> i_buffer]-> Bounds(), 
139                                  p_win-> voutWindow-> Bounds() );  
140         p_win-> voutWindow-> UnlockLooper(); 
141     } 
142     return B_OK; 
143 }
144
145 /*****************************************************************************
146  * bitmapWindow : This is the bitmap window output
147  *****************************************************************************/
148 bitmapWindow::bitmapWindow(BRect frame, VideoWindow *theOwner)
149         : BWindow( frame, NULL, B_TITLED_WINDOW, 
150                    B_OUTLINE_RESIZE | B_NOT_CLOSABLE | B_NOT_MINIMIZABLE )
151 {
152     is_zoomed = false;
153     origRect = frame;
154     owner = theOwner;
155     SetTitle(VOUT_TITLE " (BBitmap output)");
156 }
157
158 bitmapWindow::~bitmapWindow()
159 {
160 }
161
162 void bitmapWindow::FrameResized( float width, float height )
163 {
164         if (is_zoomed)
165         {
166             return;
167         }
168         float width_scale;
169         float height_scale;
170
171         width_scale = width / origRect.Width();
172         height_scale = height / origRect.Height();
173         
174     /* if the width is proportionally smaller */
175     if (width_scale <= height_scale)
176     {
177         ResizeTo(width, origRect.Height() * width_scale);
178     }
179     else /* if the height is proportionally smaller */
180     {
181         ResizeTo(origRect.Width() * height_scale, height);
182     }
183 }
184
185 void bitmapWindow::Zoom(BPoint origin, float width, float height )
186 {
187         if(is_zoomed)
188         {
189                 MoveTo(origRect.left, origRect.top);
190                 ResizeTo(origRect.IntegerWidth(), origRect.IntegerHeight());
191                 be_app->ShowCursor();
192         }
193         else
194         {
195                 BScreen *screen;
196                 screen = new BScreen(this);
197                 BRect rect = screen->Frame();
198                 delete screen;
199                 MoveTo(0,0);
200                 ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
201                 be_app->HideCursor();
202         }
203         is_zoomed = !is_zoomed;
204 }
205
206 /*****************************************************************************
207  * directWindow : This is the bitmap window output
208  *****************************************************************************/
209 directWindow::directWindow(BRect frame, VideoWindow *theOwner)
210         : BDirectWindow( frame, NULL, B_TITLED_WINDOW, 
211                    B_OUTLINE_RESIZE | B_NOT_CLOSABLE | B_NOT_MINIMIZABLE )
212 {
213     is_zoomed = false;
214     origRect = frame;
215     owner = theOwner;
216     SetTitle(VOUT_TITLE " (DirectWindow output)");
217 }
218
219 directWindow::~directWindow()
220 {
221 }
222
223 void directWindow::DirectConnected(direct_buffer_info *info)
224 {
225 }
226
227 void directWindow::FrameResized( float width, float height )
228 {
229         if (is_zoomed)
230         {
231             return;
232         }
233         float width_scale;
234         float height_scale;
235
236         width_scale = width / origRect.Width();
237         height_scale = height / origRect.Height();
238         
239     /* if the width is proportionally smaller */
240     if (width_scale <= height_scale)
241     {
242         ResizeTo(width, origRect.Height() * width_scale);
243     }
244     else /* if the height is proportionally smaller */
245     {
246         ResizeTo(origRect.Width() * height_scale, height);
247     }
248 }
249
250 void directWindow::Zoom(BPoint origin, float width, float height )
251 {
252         if(is_zoomed)
253         {
254             SetFullScreen(false);
255                 MoveTo(origRect.left, origRect.top);
256                 ResizeTo(origRect.IntegerWidth(), origRect.IntegerHeight());
257                 be_app->ShowCursor();
258         }
259         else
260         {
261                 SetFullScreen(true);
262                 BScreen *screen;
263                 screen = new BScreen(this);
264                 BRect rect = screen->Frame();
265                 delete screen;
266                 MoveTo(0,0);
267                 ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
268                 be_app->HideCursor();
269         }
270         is_zoomed = !is_zoomed;
271 }
272
273 /*****************************************************************************
274  * VideoWindow constructor and destructor
275  *****************************************************************************/
276 VideoWindow::VideoWindow( int width, int height, 
277                           vout_thread_t *p_video_output )
278 {
279     if ( BDirectWindow::SupportsWindowMode() )
280     { 
281         voutWindow = new directWindow( BRect( 80, 50, 
282                                               80 + width, 50 + height ), this );
283     }
284     else
285     {
286             voutWindow = new bitmapWindow( BRect( 80, 50, 
287                                               80 + width, 50 + height ), this );
288         }
289
290         /* set the VideoWindow variables */
291     teardownwindow = false;
292         
293         /* create the view to do the display */
294     view = new VLCView( voutWindow->Bounds() );
295     voutWindow->AddChild(view);
296     
297     /* Bitmap mode overlay not available */
298         bitmap[0] = new BBitmap( voutWindow->Bounds(), B_RGB32);
299         bitmap[1] = new BBitmap( voutWindow->Bounds(), B_RGB32);
300         memset(bitmap[0]->Bits(), 0, bitmap[0]->BitsLength());
301         memset(bitmap[1]->Bits(), 0, bitmap[1]->BitsLength());
302
303         i_width = bitmap[0]->Bounds().IntegerWidth();
304         i_height = bitmap[0]->Bounds().IntegerHeight();
305
306     voutWindow->Show();
307 }
308
309 VideoWindow::~VideoWindow()
310 {
311     int32 result;
312
313     voutWindow->Hide();
314     voutWindow->Sync();
315     voutWindow->Lock();
316     voutWindow->Quit();
317     teardownwindow = true;
318     wait_for_thread(fDrawThreadID, &result);
319         delete bitmap[0];
320         delete bitmap[1];
321 }
322
323 void VideoWindow::resizeIfRequired( int newWidth, int newHeight )
324 {
325     if (( newWidth != i_width + 1) &&
326         ( newHeight != i_height + 1) &&
327         ( newWidth != 0 ))
328     {
329         if ( voutWindow->Lock() )
330         {
331             view->ClearViewBitmap();
332             i_width = newWidth - 1;
333             i_height = newHeight -1;
334             voutWindow->ResizeTo((float) i_width, (float) i_height); 
335             voutWindow->Unlock();
336         }
337     }
338 }
339
340 void VideoWindow::drawBuffer(int bufferIndex)
341 {
342         status_t status;
343         
344         i_buffer = bufferIndex; 
345         
346     fDrawThreadID = spawn_thread(Draw, "drawing_thread",
347                     B_DISPLAY_PRIORITY, (void*) this);
348     wait_for_thread(fDrawThreadID, &status);
349 }
350
351 /*****************************************************************************
352  * VLCView::VLCView
353  *****************************************************************************/
354 VLCView::VLCView(BRect bounds) : BView(bounds, "", B_FOLLOW_ALL, B_WILL_DRAW)
355 {
356         SetViewColor(B_TRANSPARENT_32_BIT);
357 }
358
359 /*****************************************************************************
360  * VLCView::~VLCView
361  *****************************************************************************/
362 VLCView::~VLCView()
363 {
364 }
365
366 /*****************************************************************************
367  * VLCVIew::~VLCView
368  *****************************************************************************/
369 void VLCView::MouseDown(BPoint point)
370 {
371         BWindow *win = Window();
372         win->Zoom();
373 }
374
375 extern "C"
376 {
377
378 /*****************************************************************************
379  * Local prototypes
380  *****************************************************************************/
381 static int  vout_Probe      ( probedata_t *p_data );
382 static int  vout_Create     ( struct vout_thread_s * );
383 static int  vout_Init       ( struct vout_thread_s * );
384 static void vout_End        ( struct vout_thread_s * );
385 static void vout_Destroy    ( struct vout_thread_s * );
386 static int  vout_Manage     ( struct vout_thread_s * );
387 static void vout_Display    ( struct vout_thread_s * );
388
389 static int  BeosOpenDisplay ( vout_thread_t *p_vout );
390 static void BeosCloseDisplay( vout_thread_t *p_vout );
391
392 /*****************************************************************************
393  * Functions exported as capabilities. They are declared as static so that
394  * we don't pollute the namespace too much.
395  *****************************************************************************/
396 void _M( vout_getfunctions )( function_list_t * p_function_list )
397 {
398     p_function_list->pf_probe = vout_Probe;
399     p_function_list->functions.vout.pf_create     = vout_Create;
400     p_function_list->functions.vout.pf_init       = vout_Init;
401     p_function_list->functions.vout.pf_end        = vout_End;
402     p_function_list->functions.vout.pf_destroy    = vout_Destroy;
403     p_function_list->functions.vout.pf_manage     = vout_Manage;
404     p_function_list->functions.vout.pf_display    = vout_Display;
405     p_function_list->functions.vout.pf_setpalette = NULL;
406 }
407
408 /*****************************************************************************
409  * vout_Probe: probe the video driver and return a score
410  *****************************************************************************
411  * This function tries to initialize SDL and returns a score to the
412  * plugin manager so that it can select the best plugin.
413  *****************************************************************************/
414 static int vout_Probe( probedata_t *p_data )
415 {
416     if( TestMethod( VOUT_METHOD_VAR, "beos" ) )
417     {
418         return( 999 );
419     }
420     return( 100 );
421 }
422
423 /*****************************************************************************
424  * vout_Create: allocates BeOS video thread output method
425  *****************************************************************************
426  * This function allocates and initializes a BeOS vout method.
427  *****************************************************************************/
428 int vout_Create( vout_thread_t *p_vout )
429 {
430     /* Allocate structure */
431     p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
432     if( p_vout->p_sys == NULL )
433     {
434         intf_ErrMsg( "error: %s", strerror(ENOMEM) );
435         return( 1 );
436     }
437     
438     /* force scaling off */
439         p_vout->b_scale = false;
440
441     /* Open and initialize device */
442     if( BeosOpenDisplay( p_vout ) )
443     {
444         intf_ErrMsg("vout error: can't open display");
445         free( p_vout->p_sys );
446         return( 1 );
447     }
448
449     return( 0 );
450 }
451
452 /*****************************************************************************
453  * vout_Init: initialize BeOS video thread output method
454  *****************************************************************************/
455 int vout_Init( vout_thread_t *p_vout )
456 {
457     VideoWindow * p_win = p_vout->p_sys->p_window;
458
459     if((p_win->bitmap[0] != NULL) && (p_win->bitmap[1] != NULL))
460         {
461         p_vout->pf_setbuffers( p_vout,
462                (byte_t *)p_win->bitmap[0]->Bits(),
463                (byte_t *)p_win->bitmap[1]->Bits());
464     }
465     return( 0 );
466 }
467
468 /*****************************************************************************
469  * vout_End: terminate BeOS video thread output method
470  *****************************************************************************/
471 void vout_End( vout_thread_t *p_vout )
472 {
473         /* place code here to end the video */
474 }
475
476 /*****************************************************************************
477  * vout_Destroy: destroy BeOS video thread output method
478  *****************************************************************************
479  * Terminate an output method created by DummyCreateOutputMethod
480  *****************************************************************************/
481 void vout_Destroy( vout_thread_t *p_vout )
482 {
483     BeosCloseDisplay( p_vout );
484     free( p_vout->p_sys );
485 }
486
487 /*****************************************************************************
488  * vout_Manage: handle BeOS events
489  *****************************************************************************
490  * This function should be called regularly by video output thread. It manages
491  * console events. It returns a non null value on error.
492  *****************************************************************************/
493 int vout_Manage( vout_thread_t *p_vout )
494 {
495     VideoWindow * p_win = p_vout->p_sys->p_window;
496     
497     p_win->resizeIfRequired(p_vout->p_buffer[p_vout->i_buffer_index].i_pic_width,
498                             p_vout->p_buffer[p_vout->i_buffer_index].i_pic_height);
499                             
500         return( 0 );
501 }
502
503 /*****************************************************************************
504  * vout_Display: displays previously rendered output
505  *****************************************************************************
506  * This function send the currently rendered image to BeOS image, waits until
507  * it is displayed and switch the two rendering buffers, preparing next frame.
508  *****************************************************************************/
509 void vout_Display( vout_thread_t *p_vout )
510 {
511
512     VideoWindow * p_win = p_vout->p_sys->p_window;
513     /* draw buffer if required */    
514         if (!p_win->teardownwindow)
515         {
516        p_win->drawBuffer(p_vout->i_buffer_index);
517     }
518     /* change buffer */
519         p_vout->i_buffer_index = ++p_vout->i_buffer_index & 1;
520 }
521
522 /* following functions are local */
523
524 /*****************************************************************************
525  * BeosOpenDisplay: open and initialize BeOS device
526  *****************************************************************************/
527 static int BeosOpenDisplay( vout_thread_t *p_vout )
528
529     
530     VideoWindow * p_win = new VideoWindow( p_vout->i_width - 1, 
531                                            p_vout->i_height - 1, 
532                                            p_vout );
533
534     if( p_win == 0 )
535     {
536         free( p_vout->p_sys );
537         intf_ErrMsg( "error: cannot allocate memory for VideoWindow" );
538         return( 1 );
539     }   
540     
541     p_vout->p_sys->p_window = p_win;
542     /* set the system to 32bits always
543        let BeOS do all the work */
544         p_vout->b_YCbr            = false;
545     p_vout->i_screen_depth    = BITS_PER_PLANE;
546     p_vout->i_bytes_per_pixel = BYTES_PER_PIXEL;
547     p_vout->i_width           = p_win->i_width + 1;
548     p_vout->i_height          = p_win->i_height + 1;
549     p_vout->i_bytes_per_line  = p_vout->i_width * BYTES_PER_PIXEL;
550
551     p_vout->i_red_mask =        0xff0000;
552     p_vout->i_green_mask =      0x00ff00;
553     p_vout->i_blue_mask =       0x0000ff;
554
555     return( 0 );
556 }
557
558 /*****************************************************************************
559  * BeosDisplay: close and reset BeOS device
560  *****************************************************************************
561  * Returns all resources allocated by BeosOpenDisplay and restore the original
562  * state of the device.
563  *****************************************************************************/
564 static void BeosCloseDisplay( vout_thread_t *p_vout )
565 {    
566     /* Destroy the video window */
567     delete p_vout->p_sys->p_window;
568 }
569
570 } /* extern "C" */