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