1 /* 2 * Copyright 2006-2009 Stephan Aßmus <superstippi@gmx.de> 3 * All rights reserved. Distributed under the terms of the MIT license. 4 */ 5 6 7 #include "VideoView.h" 8 9 #include <stdio.h> 10 11 // XXX: Hack for BeOS: REMOVE ME later 12 #ifndef __HAIKU__ 13 #define private public 14 #define BitmapFlags(b) ((b)->fFlags) 15 #else 16 #define BitmapFlags(b) ((b)->Flags()) 17 #endif 18 #include <Bitmap.h> 19 #ifndef __HAIKU__ 20 #undef private 21 #endif 22 23 #include <Application.h> 24 #include <WindowScreen.h> 25 26 #include "Settings.h" 27 28 29 VideoView::VideoView(BRect frame, const char* name, uint32 resizeMask) 30 : 31 BView(frame, name, resizeMask, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE 32 | B_PULSE_NEEDED), 33 fOverlayMode(false), 34 fIsPlaying(false), 35 fIsFullscreen(false), 36 fLastMouseMove(system_time()), 37 fGlobalSettingsListener(this) 38 { 39 SetViewColor(B_TRANSPARENT_COLOR); 40 // might be reset to overlay key color if overlays are used 41 SetHighColor(0, 0, 0); 42 43 // create some hopefully sensible default overlay restrictions 44 // they will be adjusted when overlays are actually used 45 fOverlayRestrictions.min_width_scale = 0.25; 46 fOverlayRestrictions.max_width_scale = 8.0; 47 fOverlayRestrictions.min_height_scale = 0.25; 48 fOverlayRestrictions.max_height_scale = 8.0; 49 50 Settings::Default()->AddListener(&fGlobalSettingsListener); 51 _AdoptGlobalSettings(); 52 } 53 54 55 VideoView::~VideoView() 56 { 57 Settings::Default()->RemoveListener(&fGlobalSettingsListener); 58 } 59 60 61 void 62 VideoView::Draw(BRect updateRect) 63 { 64 bool fillBlack = true; 65 66 if (LockBitmap()) { 67 if (const BBitmap* bitmap = GetBitmap()) { 68 fillBlack = false; 69 if (!fOverlayMode) 70 _DrawBitmap(bitmap); 71 } 72 UnlockBitmap(); 73 } 74 75 if (fillBlack) 76 FillRect(updateRect); 77 } 78 79 80 void 81 VideoView::MessageReceived(BMessage* message) 82 { 83 switch (message->what) { 84 case MSG_OBJECT_CHANGED: 85 // received from fGlobalSettingsListener 86 // TODO: find out which object, if we ever watch more than 87 // the global settings instance... 88 _AdoptGlobalSettings(); 89 break; 90 default: 91 BView::MessageReceived(message); 92 } 93 } 94 95 96 void 97 VideoView::Pulse() 98 { 99 if (!fIsFullscreen || !fIsPlaying) 100 return; 101 102 bigtime_t now = system_time(); 103 if (now - fLastMouseMove > 2LL * 1000000) { 104 fLastMouseMove = now; 105 // take care of disabling the screen saver 106 BPoint where; 107 uint32 buttons; 108 GetMouse(&where, &buttons, false); 109 if (buttons == 0) { 110 ConvertToScreen(&where); 111 set_mouse_position((int32)where.x, (int32)where.y); 112 // hide the mouse cursor until the user moves it 113 be_app->ObscureCursor(); 114 } 115 } 116 } 117 118 119 void 120 VideoView::MouseMoved(BPoint where, uint32 transit, 121 const BMessage* dragMessage) 122 { 123 fLastMouseMove = system_time(); 124 } 125 126 127 // #pragma mark - 128 129 130 void 131 VideoView::SetBitmap(const BBitmap* bitmap) 132 { 133 VideoTarget::SetBitmap(bitmap); 134 // Attention: Don't lock the window, if the bitmap is NULL. Otherwise 135 // we're going to deadlock when the window tells the node manager to 136 // stop the nodes (Window -> NodeManager -> VideoConsumer -> VideoView 137 // -> Window). 138 if (!bitmap || LockLooperWithTimeout(10000) != B_OK) 139 return; 140 141 if (LockBitmap()) { 142 if (fOverlayMode 143 || (BitmapFlags(bitmap) & B_BITMAP_WILL_OVERLAY) != 0) { 144 if (!fOverlayMode) { 145 // init overlay 146 rgb_color key; 147 status_t ret = SetViewOverlay(bitmap, bitmap->Bounds(), 148 Bounds(), &key, B_FOLLOW_ALL, 149 B_OVERLAY_FILTER_HORIZONTAL 150 | B_OVERLAY_FILTER_VERTICAL); 151 if (ret == B_OK) { 152 fOverlayKeyColor = key; 153 SetViewColor(key); 154 SetLowColor(key); 155 snooze(20000); 156 FillRect(Bounds(), B_SOLID_LOW); 157 Sync(); 158 // use overlay from here on 159 fOverlayMode = true; 160 161 // update restrictions 162 overlay_restrictions restrictions; 163 if (bitmap->GetOverlayRestrictions(&restrictions) 164 == B_OK) 165 fOverlayRestrictions = restrictions; 166 } else { 167 // try again next time 168 // synchronous draw 169 FillRect(Bounds()); 170 Sync(); 171 } 172 } else { 173 // transfer overlay channel 174 rgb_color key; 175 SetViewOverlay(bitmap, bitmap->Bounds(), Bounds(), 176 &key, B_FOLLOW_ALL, B_OVERLAY_FILTER_HORIZONTAL 177 | B_OVERLAY_FILTER_VERTICAL 178 | B_OVERLAY_TRANSFER_CHANNEL); 179 } 180 } else if (fOverlayMode 181 && (BitmapFlags(bitmap) & B_BITMAP_WILL_OVERLAY) == 0) { 182 fOverlayMode = false; 183 ClearViewOverlay(); 184 SetViewColor(B_TRANSPARENT_COLOR); 185 } 186 if (!fOverlayMode) 187 _DrawBitmap(bitmap); 188 189 UnlockBitmap(); 190 } 191 UnlockLooper(); 192 } 193 194 195 void 196 VideoView::GetOverlayScaleLimits(float* minScale, float* maxScale) const 197 { 198 *minScale = max_c(fOverlayRestrictions.min_width_scale, 199 fOverlayRestrictions.min_height_scale); 200 *maxScale = max_c(fOverlayRestrictions.max_width_scale, 201 fOverlayRestrictions.max_height_scale); 202 } 203 204 205 void 206 VideoView::OverlayScreenshotPrepare() 207 { 208 // TODO: Do nothing if the current bitmap is in RGB color space 209 // and no overlay. Otherwise, convert current bitmap to RGB color 210 // space an draw it in place of the normal display. 211 } 212 213 214 void 215 VideoView::OverlayScreenshotCleanup() 216 { 217 // TODO: Do nothing if the current bitmap is in RGB color space 218 // and no overlay. Otherwise clean view area with overlay color. 219 } 220 221 222 bool 223 VideoView::UseOverlays() const 224 { 225 return fUseOverlays; 226 } 227 228 229 bool 230 VideoView::IsOverlayActive() 231 { 232 bool active = false; 233 if (LockBitmap()) { 234 active = fOverlayMode; 235 UnlockBitmap(); 236 } 237 return active; 238 } 239 240 241 void 242 VideoView::DisableOverlay() 243 { 244 if (!fOverlayMode) 245 return; 246 247 FillRect(Bounds()); 248 Sync(); 249 250 ClearViewOverlay(); 251 snooze(20000); 252 Sync(); 253 fOverlayMode = false; 254 } 255 256 257 void 258 VideoView::SetPlaying(bool playing) 259 { 260 fIsPlaying = playing; 261 } 262 263 264 void 265 VideoView::SetFullscreen(bool fullScreen) 266 { 267 fIsFullscreen = fullScreen; 268 } 269 270 271 // #pragma mark - 272 273 274 void 275 VideoView::_DrawBitmap(const BBitmap* bitmap) 276 { 277 #ifdef __HAIKU__ 278 uint32 options = fUseBilinearScaling ? B_FILTER_BITMAP_BILINEAR : 0; 279 DrawBitmap(bitmap, bitmap->Bounds(), Bounds(), options); 280 #else 281 DrawBitmap(bitmap, bitmap->Bounds(), Bounds()); 282 #endif 283 } 284 285 286 void 287 VideoView::_AdoptGlobalSettings() 288 { 289 mpSettings settings = Settings::CurrentSettings(); 290 // thread safe 291 292 fUseOverlays = settings.useOverlays; 293 fUseBilinearScaling = settings.scaleBilinear; 294 295 if (!fIsPlaying && !fOverlayMode) 296 Invalidate(); 297 } 298 299