]> git.sesse.net Git - vlc/blob - plugins/beos/vout_beos.cpp
* The Gtk+ interface is now built as a Debian package as well. The Gnome
[vlc] / plugins / beos / vout_beos.cpp
1 /*****************************************************************************
2  * vout_beos.cpp: beos video output display method
3  *****************************************************************************
4  * Copyright (C) 2000, 2001 VideoLAN
5  *
6  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
7  *          Samuel Hocevar <sam@zoy.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #define MODULE_NAME beos
25 #include "modules_inner.h"
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include "defs.h"
31
32 #include <errno.h>                                                 /* ENOMEM */
33 #include <stdlib.h>                                                /* free() */
34 #include <stdio.h>
35 #include <string.h>                                            /* strerror() */
36 #include <kernel/OS.h>
37 #include <Message.h>
38 #include <View.h>
39 #include <Window.h>
40 #include <Bitmap.h>
41 #include <Application.h>
42 #include <malloc.h>
43 #include <string.h>
44
45 extern "C"
46 {
47 #include "config.h"
48 #include "common.h"
49 #include "threads.h"
50 #include "mtime.h"
51 #include "tests.h"
52 #include "modules.h"
53
54 #include "video.h"
55 #include "video_output.h"
56
57 #include "interface.h" /* XXX maybe to remove if window.h is splitted */
58 #include "intf_msg.h"
59
60 #include "main.h"
61 }
62
63 #include "window.h"
64
65 #define WIDTH 128
66 #define HEIGHT 64
67 #define BITS_PER_PLANE 16
68 #define BYTES_PER_PIXEL 2
69
70 /*****************************************************************************
71  * vout_sys_t: BeOS video output method descriptor
72  *****************************************************************************
73  * This structure is part of the video output thread descriptor.
74  * It describes the BeOS specific properties of an output thread.
75  *****************************************************************************/
76  
77 typedef struct vout_sys_s
78 {
79     VideoWindow *         p_window;
80
81     BBitmap *             pp_bitmap[2];
82     s32                   i_width;
83     s32                   i_height;
84     boolean_t             b_overlay_enabled;
85 } vout_sys_t;
86
87
88 /*****************************************************************************
89  * beos_GetAppWindow : retrieve a BWindow pointer from the window name
90  *****************************************************************************/
91
92 BWindow *beos_GetAppWindow(char *name)
93 {
94     int32       index;
95     BWindow     *window;
96     
97     for (index = 0 ; ; index++)
98     {
99         window = be_app->WindowAt(index);
100         if (window == NULL)
101             break;
102         if (window->LockWithTimeout(200000) == B_OK)
103         {
104             if (strcmp(window->Name(), name) == 0)
105             {
106                 window->Unlock();
107                 break;
108             }
109             window->Unlock();
110         }
111     }
112     return window; 
113 }
114
115 /*****************************************************************************
116  * VideoWindow constructor and destructor
117  *****************************************************************************/
118
119 VideoWindow::VideoWindow(BRect frame, const char *name, vout_thread_t *p_video_output )
120         : BWindow(frame, name, B_TITLED_WINDOW, 0)
121 {
122     p_vout = p_video_output;
123
124     p_view = new BView(Bounds(), "", B_FOLLOW_ALL, B_WILL_DRAW);
125     p_view->SetViewColor(0,0,0); /* set the background to black */
126     AddChild(p_view);
127
128     Show();
129 }
130
131 VideoWindow::~VideoWindow()
132 {
133 }
134
135 /*****************************************************************************
136  * VideoWindow::FrameResized
137  *****************************************************************************/
138
139 void VideoWindow::FrameResized( float width, float height )
140 {
141     //b_resized = 1;
142 }
143
144 /*****************************************************************************
145  * VideoWindow::MessageReceived
146  *****************************************************************************/
147
148 void VideoWindow::MessageReceived( BMessage * p_message )
149 {
150     BWindow * p_win;
151     
152     switch( p_message->what )
153     {
154     case B_KEY_DOWN:
155     case B_SIMPLE_DATA:
156         // post the message to the interface window which will handle it
157         p_win = beos_GetAppWindow( "interface" );
158         if( p_win != NULL )
159         {
160             p_win->PostMessage( p_message );
161         }
162         break;
163     
164     default:
165         BWindow::MessageReceived( p_message );
166         break;
167     }
168 }
169
170 /*****************************************************************************
171  * VideoWindow::QuitRequested
172  *****************************************************************************/
173
174 bool VideoWindow::QuitRequested()
175 {
176     /* FIXME: send a message ! */
177     p_main->p_intf->b_die = 1;
178
179     return( false );
180 }
181
182 extern "C"
183 {
184
185 /*****************************************************************************
186  * Local prototypes
187  *****************************************************************************/
188 static int  vout_Probe      ( probedata_t *p_data );
189 static int  vout_Create     ( struct vout_thread_s * );
190 static int  vout_Init       ( struct vout_thread_s * );
191 static void vout_End        ( struct vout_thread_s * );
192 static void vout_Destroy    ( struct vout_thread_s * );
193 static int  vout_Manage     ( struct vout_thread_s * );
194 static void vout_Display    ( struct vout_thread_s * );
195
196 static int  BeosOpenDisplay ( vout_thread_t *p_vout );
197 static void BeosCloseDisplay( vout_thread_t *p_vout );
198
199 /*****************************************************************************
200  * Functions exported as capabilities. They are declared as static so that
201  * we don't pollute the namespace too much.
202  *****************************************************************************/
203 void _M( vout_getfunctions )( function_list_t * p_function_list )
204 {
205     p_function_list->pf_probe = vout_Probe;
206     p_function_list->functions.vout.pf_create     = vout_Create;
207     p_function_list->functions.vout.pf_init       = vout_Init;
208     p_function_list->functions.vout.pf_end        = vout_End;
209     p_function_list->functions.vout.pf_destroy    = vout_Destroy;
210     p_function_list->functions.vout.pf_manage     = vout_Manage;
211     p_function_list->functions.vout.pf_display    = vout_Display;
212     p_function_list->functions.vout.pf_setpalette = NULL;
213 }
214
215 /*****************************************************************************
216  * vout_Probe: probe the video driver and return a score
217  *****************************************************************************
218  * This function tries to initialize SDL and returns a score to the
219  * plugin manager so that it can select the best plugin.
220  *****************************************************************************/
221 static int vout_Probe( probedata_t *p_data )
222 {
223     if( TestMethod( VOUT_METHOD_VAR, "beos" ) )
224     {
225         return( 999 );
226     }
227
228     return( 100 );
229 }
230
231 /*****************************************************************************
232  * vout_Create: allocates BeOS video thread output method
233  *****************************************************************************
234  * This function allocates and initializes a BeOS vout method.
235  *****************************************************************************/
236 int vout_Create( vout_thread_t *p_vout )
237 {
238     /* Allocate structure */
239     p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
240     if( p_vout->p_sys == NULL )
241     {
242         intf_ErrMsg( "error: %s", strerror(ENOMEM) );
243         return( 1 );
244     }
245     
246     /* Set video window's size */
247     p_vout->i_width =  main_GetIntVariable( VOUT_WIDTH_VAR,
248                                             VOUT_WIDTH_DEFAULT );
249     p_vout->i_height = main_GetIntVariable( VOUT_HEIGHT_VAR,
250                                             VOUT_HEIGHT_DEFAULT );
251
252     /* Open and initialize device */
253     if( BeosOpenDisplay( p_vout ) )
254     {
255         intf_ErrMsg("vout error: can't open display");
256         free( p_vout->p_sys );
257         return( 1 );
258     }
259
260     return( 0 );
261 }
262
263 /*****************************************************************************
264  * vout_Init: initialize BeOS video thread output method
265  *****************************************************************************/
266 int vout_Init( vout_thread_t *p_vout )
267 {
268     VideoWindow * p_win = p_vout->p_sys->p_window;
269     BBitmap **const & p_bmp = p_vout->p_sys->pp_bitmap;
270
271     p_win->Lock();
272     
273     p_vout->p_sys->i_width =            p_vout->i_width;
274     p_vout->p_sys->i_height =           p_vout->i_height;
275     p_vout->p_sys->b_overlay_enabled =  false;
276
277     /*
278      * Create the two bitmaps we need for double buffering
279      */
280     BRect bounds = BRect( 0, 0, p_vout->i_width-1, p_vout->i_height-1 );
281
282     /* First we try to create an overlay bitmap */
283     p_bmp[0] = new BBitmap( bounds,
284         B_BITMAP_WILL_OVERLAY | B_BITMAP_RESERVE_OVERLAY_CHANNEL,
285         B_YCbCr420 );
286     p_bmp[1] = new BBitmap( bounds,
287         B_BITMAP_WILL_OVERLAY | B_BITMAP_RESERVE_OVERLAY_CHANNEL,
288         B_YCbCr420 );
289     
290     if( p_bmp[0]->InitCheck() == B_OK && p_bmp[1]->InitCheck() == B_OK )
291     {
292         p_vout->p_sys->b_overlay_enabled = true;
293     }
294     else
295     {
296         delete p_bmp[0];
297         delete p_bmp[1];
298     }
299     
300     /* We failed to create overlay bitmaps, use standard bmp instead */
301     if( !p_vout->p_sys->b_overlay_enabled )
302     {
303         p_bmp[0] = new BBitmap( bounds, B_RGB32 );
304         p_bmp[1] = new BBitmap( bounds, B_RGB32 );
305         if( p_bmp[0]->InitCheck() != B_OK || p_bmp[1]->InitCheck() != B_OK )
306         {
307             delete p_bmp[0];
308             delete p_bmp[1];
309             intf_ErrMsg( "vout error: failed to create BBitmap" );
310             return( 1 );
311         }
312     }
313
314     p_vout->b_need_render = !p_vout->p_sys->b_overlay_enabled;
315     intf_Msg( "vout: YUV acceleration %s",
316         p_vout->p_sys->b_overlay_enabled ? "activated" : "unavailable !" ); 
317  
318     /* Initialize the bitmap buffers to black (0,0,0) */
319     memset( p_bmp[0]->Bits(), 0, p_bmp[0]->BitsLength() );
320     memset( p_bmp[1]->Bits(), 0, p_bmp[1]->BitsLength() );
321
322      /* Set and initialize buffers */
323     vout_SetBuffers( p_vout, p_bmp[0]->Bits(), p_bmp[1]->Bits() );
324
325     p_win->Unlock();
326
327     return( 0 );
328 }
329
330 /*****************************************************************************
331  * vout_End: terminate BeOS video thread output method
332  *****************************************************************************/
333 void vout_End( vout_thread_t *p_vout )
334 {
335    VideoWindow * p_win = p_vout->p_sys->p_window;
336    
337    p_win->Lock();
338    
339    delete p_vout->p_sys->pp_bitmap[0];
340    delete p_vout->p_sys->pp_bitmap[1];
341
342    p_win->Unlock();   
343 }
344
345 /*****************************************************************************
346  * vout_Destroy: destroy BeOS video thread output method
347  *****************************************************************************
348  * Terminate an output method created by DummyCreateOutputMethod
349  *****************************************************************************/
350 void vout_Destroy( vout_thread_t *p_vout )
351 {
352     BeosCloseDisplay( p_vout );
353     
354     free( p_vout->p_sys );
355 }
356
357 /*****************************************************************************
358  * vout_Manage: handle BeOS events
359  *****************************************************************************
360  * This function should be called regularly by video output thread. It manages
361  * console events. It returns a non null value on error.
362  *****************************************************************************/
363 int vout_Manage( vout_thread_t *p_vout )
364 {
365     if( p_vout->p_sys->p_window->b_resized )
366     {
367         p_vout->p_sys->p_window->b_resized = 0;
368         p_vout->i_changes |= VOUT_SIZE_CHANGE;
369     }
370
371     /* XXX: I doubt that this code is working correctly (Polux) */
372     if( p_vout->i_changes & VOUT_SIZE_CHANGE )
373     {
374        intf_WarnMsg( 1, "resizing window" );
375         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
376
377         /* Resize window */
378         p_vout->p_sys->p_window->ResizeTo( p_vout->i_width, p_vout->i_height );
379
380         /* Destroy XImages to change their size */
381         vout_End( p_vout );
382
383         /* Recreate XImages. If SysInit failed, the thread can't go on. */
384         if( vout_Init( p_vout ) )
385         {
386             intf_ErrMsg( "error: can't resize display" );
387             return( 1 );
388         }
389
390         /* Tell the video output thread that it will need to rebuild YUV
391          * tables. This is needed since convertion buffer size may have
392          * changed */
393         p_vout->i_changes |= VOUT_YUV_CHANGE;
394         intf_Msg( "vout: video display resized (%dx%d)",
395                   p_vout->i_width, p_vout->i_height );
396     }
397
398     return( 0 );
399 }
400
401 /*****************************************************************************
402  * vout_Display: displays previously rendered output
403  *****************************************************************************
404  * This function send the currently rendered image to BeOS image, waits until
405  * it is displayed and switch the two rendering buffers, preparing next frame.
406  *****************************************************************************/
407 void vout_Display( vout_thread_t *p_vout )
408 {
409     VideoWindow * p_win = p_vout->p_sys->p_window;
410     BBitmap **const & p_bmp = p_vout->p_sys->pp_bitmap;
411
412     p_win->Lock();
413     
414     p_vout->i_buffer_index = ++p_vout->i_buffer_index & 1;
415     if( p_vout->p_sys->b_overlay_enabled )
416     {
417         rgb_color key;
418         p_win->p_view->ClearViewOverlay();
419                 p_win->p_view->SetViewOverlay( p_bmp[p_vout->i_buffer_index],
420             p_bmp[p_vout->i_buffer_index]->Bounds(),
421             p_win->p_view->Bounds(), &key, B_FOLLOW_ALL,
422                         B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL );
423                 p_win->p_view->SetViewColor( key );
424     }
425     else
426     {
427         p_win->p_view->DrawBitmap( p_bmp[p_vout->i_buffer_index],
428             p_win->p_view->Bounds() );
429     }
430     
431     p_win->Unlock();
432 }
433
434 /* following functions are local */
435
436 /*****************************************************************************
437  * BeosOpenDisplay: open and initialize BeOS device
438  *****************************************************************************/
439
440 static int BeosOpenDisplay( vout_thread_t *p_vout )
441
442     /* Create the video window */
443     p_vout->p_sys->p_window =
444         new VideoWindow(  BRect( 50, 150, 50+p_vout->i_width-1, 150+p_vout->i_height-1 ), VOUT_TITLE " (BeOS output) - drop a file here to play it !", p_vout );
445     if( p_vout->p_sys->p_window == 0 )
446     {
447         free( p_vout->p_sys );
448         intf_ErrMsg( "error: cannot allocate memory for VideoWindow" );
449         return( 1 );
450     }   
451     
452     /* XXX: 32 is only chosen for test purposes */
453     p_vout->i_screen_depth =         32;
454     p_vout->i_bytes_per_pixel =      4;
455     p_vout->i_bytes_per_line =       p_vout->i_width*p_vout->i_bytes_per_pixel;
456     
457     switch( p_vout->i_screen_depth )
458     {
459     case 8:
460         intf_ErrMsg( "vout error: 8 bit mode not fully supported" );
461         return( 1 );
462     case 15:
463         p_vout->i_red_mask =        0x7c00;
464         p_vout->i_green_mask =      0x03e0;
465         p_vout->i_blue_mask =       0x001f;
466         break;
467     case 16:
468         p_vout->i_red_mask =        0xf800;
469         p_vout->i_green_mask =      0x07e0;
470         p_vout->i_blue_mask =       0x001f;
471         break;
472     case 24:
473     case 32:
474     default:
475         p_vout->i_red_mask =        0xff0000;
476         p_vout->i_green_mask =      0x00ff00;
477         p_vout->i_blue_mask =       0x0000ff;
478         break;
479     }
480
481     return( 0 );
482 }
483
484 /*****************************************************************************
485  * BeosDisplay: close and reset BeOS device
486  *****************************************************************************
487  * Returns all resources allocated by BeosOpenDisplay and restore the original
488  * state of the device.
489  *****************************************************************************/
490 static void BeosCloseDisplay( vout_thread_t *p_vout )
491 {    
492     /* Destroy the video window */
493     p_vout->p_sys->p_window->Lock();
494     p_vout->p_sys->p_window->Quit();
495 }
496
497 } /* extern "C" */