vfs: check userland buffers before reading them.
[haiku.git] / src / apps / tv / VideoView.cpp
blobf127710ae78f862122c4f2cdb6dcdee215d52f50
1 /*
2 * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify,
8 * merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
25 #include <Bitmap.h>
26 #include <MediaRoster.h>
27 #include <MessageRunner.h>
28 #include "VideoView.h"
29 #include "VideoNode.h"
30 #include "ConvertBitmap.h"
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
36 #define CHECK_ACTIVITY 'ChkA'
38 VideoView::VideoView(BRect frame, const char *name, uint32 resizeMask,
39 uint32 flags)
40 : BView(frame, name, resizeMask, flags)
41 , fVideoNode(0)
42 , fVideoActive(false)
43 , fOverlayActive(false)
44 , fActivityCheckMsgRunner(0)
45 , fLastFrame(0)
47 SetViewColor(B_TRANSPARENT_COLOR);
49 status_t err = B_OK;
50 BMediaRoster *mroster = BMediaRoster::Roster(&err);
51 if (!mroster || err) {
52 printf("VideoView::VideoView: media_server is dead\n");
53 exit(1);
54 } else {
55 fVideoNode = new VideoNode("video in", this);
56 err = mroster->RegisterNode(fVideoNode);
61 VideoView::~VideoView()
63 delete fActivityCheckMsgRunner;
65 if (fVideoNode) {
66 BMediaRoster::Roster()->UnregisterNode(fVideoNode);
67 delete fVideoNode;
72 void
73 VideoView::AttachedToWindow()
75 BMessage msg(CHECK_ACTIVITY);
76 fActivityCheckMsgRunner = new BMessageRunner(BMessenger(this), &msg,
77 200000);
81 VideoNode *
82 VideoView::Node()
84 return fVideoNode;
88 void
89 VideoView::OverlayLockAcquire()
91 printf("VideoView::OverlayLockAcquire\n");
95 void
96 VideoView::OverlayLockRelease()
97 { /* [19:54] <Francois> Rudolf forwarded me a mail once about it
98 * [19:55] <Francois> when you get relmease msg you are supposed to
99 UnlockBits() on the overlay bitmaps you use
100 * [19:55] <Francois> it's used when switching workspaces
101 * [19:55] <Francois> as the bits might get relocated
103 printf("VideoView::OverlayLockRelease\n");
108 void
109 VideoView::OverlayScreenshotPrepare()
111 printf("OverlayScreenshotPrepare enter\n");
113 fVideoNode->LockBitmap();
114 if (fOverlayActive) {
115 BBitmap *bmp = fVideoNode->Bitmap();
116 if (bmp) {
117 // Window()->UpdateIfNeeded();
118 // Sync();
119 BBitmap *tmp = new BBitmap(bmp->Bounds(), 0, B_RGB32);
120 // ConvertBitmap(tmp, bmp);
121 ClearViewOverlay();
122 DrawBitmap(tmp, Bounds());
123 delete tmp;
124 // Sync();
127 fVideoNode->UnlockBitmap();
129 printf("OverlayScreenshotPrepare leave\n");
133 void
134 VideoView::OverlayScreenshotCleanup()
136 printf("OverlayScreenshotCleanup enter\n");
138 snooze(50000); // give app server some time to take the screenshot
139 fVideoNode->LockBitmap();
140 if (fOverlayActive) {
141 BBitmap *bmp = fVideoNode->Bitmap();
142 if (bmp) {
143 DrawBitmap(bmp, Bounds());
144 SetViewOverlay(bmp, bmp->Bounds(), Bounds(), &fOverlayKeyColor,
145 B_FOLLOW_ALL, B_OVERLAY_FILTER_HORIZONTAL
146 | B_OVERLAY_FILTER_VERTICAL);
147 Invalidate();
150 fVideoNode->UnlockBitmap();
152 printf("OverlayScreenshotCleanup leave\n");
156 void
157 VideoView::RemoveVideoDisplay()
159 printf("VideoView::RemoveVideoDisplay\n");
161 if (fOverlayActive) {
162 ClearViewOverlay();
163 fOverlayActive = false;
165 fVideoActive = false;
166 Invalidate();
170 void
171 VideoView::RemoveOverlay()
173 printf("VideoView::RemoveOverlay\n");
174 if (LockLooperWithTimeout(50000) == B_OK) {
175 ClearViewOverlay();
176 fOverlayActive = false;
177 UnlockLooper();
182 void
183 VideoView::CheckActivity()
185 if (!fVideoActive)
186 return;
187 if (system_time() - fLastFrame < 700000)
188 return;
190 printf("VideoView::CheckActivity: lag detected\n");
192 fVideoActive = false;
193 Invalidate();
197 void
198 VideoView::Draw(BRect updateRect)
200 if (!fVideoActive) {
201 DrawTestImage();
202 return;
204 if (fOverlayActive) {
205 SetHighColor(fOverlayKeyColor);
206 FillRect(updateRect);
207 } else {
208 fVideoNode->LockBitmap();
209 BBitmap *bmp = fVideoNode->Bitmap();
210 if (bmp)
211 DrawBitmap(bmp, bmp->Bounds(), Bounds(), B_FILTER_BITMAP_BILINEAR);
212 fVideoNode->UnlockBitmap();
217 void
218 VideoView::DrawFrame()
220 // printf("VideoView::DrawFrame\n");
221 if (!fVideoActive) {
222 fVideoActive = true;
223 if (LockLooperWithTimeout(50000) != B_OK)
224 return;
225 Invalidate();
226 UnlockLooper();
228 fLastFrame = system_time();
230 bool want_overlay = fVideoNode->IsOverlayActive();
232 if (!want_overlay && fOverlayActive) {
233 if (LockLooperWithTimeout(50000) == B_OK) {
234 ClearViewOverlay();
235 UnlockLooper();
236 fOverlayActive = false;
237 } else {
238 printf("can't ClearViewOverlay, as LockLooperWithTimeout "
239 "failed\n");
242 if (want_overlay && !fOverlayActive) {
243 fVideoNode->LockBitmap();
244 BBitmap *bmp = fVideoNode->Bitmap();
245 if (bmp && LockLooperWithTimeout(50000) == B_OK) {
246 SetViewOverlay(bmp, bmp->Bounds(), Bounds(), &fOverlayKeyColor,
247 B_FOLLOW_ALL, B_OVERLAY_FILTER_HORIZONTAL
248 | B_OVERLAY_FILTER_VERTICAL);
249 fOverlayActive = true;
251 Invalidate();
252 UnlockLooper();
254 fVideoNode->UnlockBitmap();
256 if (!fOverlayActive) {
257 if (LockLooperWithTimeout(50000) != B_OK)
258 return;
259 Invalidate();
260 UnlockLooper();
265 void
266 VideoView::DrawTestImage()
268 static const rgb_color cols[8] = {
269 {255,255,255}, {255,255,0}, {0,255,255}, {0,255,0},
270 {255,0,255}, {255,0,0}, {0,0,255}, {0,0,0}
271 // {255,255,255}, {255,255,0}, {0,255,255},
272 // {255,0,255}, {255,0,0}, {0,255,0}, {0,0,255}, {0,0,0}
274 float bar_width;
275 float left;
276 float right;
278 BRect bnd = Bounds();
279 int seperator_y1 = int(0.60 * (bnd.Height() + 1));
280 int seperator_y2 = int(0.80 * (bnd.Height() + 1));
281 int steps;
283 bar_width = bnd.Width() / 8;
284 if (bar_width < 1)
285 bar_width = 1;
287 left = 0;
288 for (int i = 0; i < 8; i++) {
289 SetHighColor(cols[i]);
290 right = (i != 7) ? left + bar_width - 1 : bnd.right;
291 FillRect(BRect(left, 0, right, seperator_y1));
292 left = right + 1;
295 steps = 32;
297 bar_width = bnd.Width() / steps;
298 // if (bar_width < 1)
299 // bar_width = 1;
301 left = 0;
302 for (int i = 0; i < steps; i++) {
303 uint8 c = i * 255 / (steps - 1);
304 SetHighColor(c, c, c);
305 right = (i != steps - 1) ? left + bar_width - 1 : bnd.right;
306 FillRect(BRect(left, seperator_y1 + 1, right, seperator_y2));
307 left = right + 1;
310 steps = 256;
312 bar_width = bnd.Width() / steps;
313 if (bar_width < 1)
314 bar_width = 1;
316 left = 0;
317 for (int i = 0; i < steps; i++) {
318 uint8 c = 255 - (i * 255 / (steps - 1));
319 SetHighColor(c, c, c);
320 right = (i != steps - 1) ? left + bar_width - 1 : bnd.right;
321 FillRect(BRect(left, seperator_y2 + 1, right, bnd.bottom));
322 left = right + 1;
327 void
328 VideoView::MessageReceived(BMessage *msg)
330 switch (msg->what) {
331 case CHECK_ACTIVITY:
332 CheckActivity();
333 break;
334 default:
335 BView::MessageReceived(msg);
340 bool
341 VideoView::IsOverlaySupported()
343 struct colorcombo {
344 color_space colspace;
345 const char *name;
346 } colspace[] = {
347 { B_RGB32, "B_RGB32"},
348 { B_RGBA32, "B_RGBA32"},
349 { B_RGB24, "B_RGB24"},
350 { B_RGB16, "B_RGB16"},
351 { B_RGB15, "B_RGB15"},
352 { B_RGBA15, "B_RGBA15"},
353 { B_RGB32_BIG, "B_RGB32_BIG"},
354 { B_RGBA32_BIG, "B_RGBA32_BIG "},
355 { B_RGB24_BIG, "B_RGB24_BIG "},
356 { B_RGB16_BIG, "B_RGB16_BIG "},
357 { B_RGB15_BIG, "B_RGB15_BIG "},
358 { B_RGBA15_BIG, "B_RGBA15_BIG "},
359 { B_YCbCr422, "B_YCbCr422"},
360 { B_YCbCr411, "B_YCbCr411"},
361 { B_YCbCr444, "B_YCbCr444"},
362 { B_YCbCr420, "B_YCbCr420"},
363 { B_YUV422, "B_YUV422"},
364 { B_YUV411, "B_YUV411"},
365 { B_YUV444, "B_YUV444"},
366 { B_YUV420, "B_YUV420"},
367 { B_NO_COLOR_SPACE, NULL}
370 bool supported = false;
371 for (int i = 0; colspace[i].name; i++) {
372 BBitmap *test = new BBitmap(BRect(0,0,320,240), B_BITMAP_WILL_OVERLAY
373 | B_BITMAP_RESERVE_OVERLAY_CHANNEL, colspace[i].colspace);
374 if (test->InitCheck() == B_OK) {
375 printf("Display supports %s (0x%08x) overlay\n", colspace[i].name,
376 colspace[i].colspace);
377 overlay_restrictions restrict;
378 if (B_OK == test->GetOverlayRestrictions(&restrict)) {
379 printf(
380 "Overlay restrictions: source horizontal_alignment %d\n",
381 restrict.source.horizontal_alignment);
382 printf("Overlay restrictions: source vertical_alignment %d\n",
383 restrict.source.vertical_alignment);
384 printf("Overlay restrictions: source width_alignment %d\n",
385 restrict.source.width_alignment);
386 printf("Overlay restrictions: source height_alignment %d\n",
387 restrict.source.height_alignment);
388 printf("Overlay restrictions: source min_width %d\n",
389 restrict.source.min_width);
390 printf("Overlay restrictions: source max_width %d\n",
391 restrict.source.max_width);
392 printf("Overlay restrictions: source min_height %d\n",
393 restrict.source.min_height);
394 printf("Overlay restrictions: source max_height %d\n",
395 restrict.source.max_height);
396 printf(
397 "Overlay restrictions: destination horizontal_alignment "
398 "%d\n", restrict.destination.horizontal_alignment);
399 printf("Overlay restrictions: destination vertical_alignment "
400 "%d\n", restrict.destination.vertical_alignment);
401 printf("Overlay restrictions: destination width_alignment "
402 "%d\n", restrict.destination.width_alignment);
403 printf("Overlay restrictions: destination height_alignment "
404 "%d\n", restrict.destination.height_alignment);
405 printf("Overlay restrictions: destination min_width %d\n",
406 restrict.destination.min_width);
407 printf("Overlay restrictions: destination max_width %d\n",
408 restrict.destination.max_width);
409 printf("Overlay restrictions: destination min_height %d\n",
410 restrict.destination.min_height);
411 printf("Overlay restrictions: destination max_height %d\n",
412 restrict.destination.max_height);
413 printf("Overlay restrictions: min_width_scale %.3f\n",
414 restrict.min_width_scale);
415 printf("Overlay restrictions: max_width_scale %.3f\n",
416 restrict.max_width_scale);
417 printf("Overlay restrictions: min_height_scale %.3f\n",
418 restrict.min_height_scale);
419 printf("Overlay restrictions: max_height_scale %.3f\n",
420 restrict.max_height_scale);
422 supported = true;
424 delete test;
425 // if (supported)
426 // break;
428 return supported;