xref: /haiku/src/apps/mediaplayer/VideoView.cpp (revision b6b0567fbd186f8ce8a0c90bdc7a7b5b4c649678)
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