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