104a91b97SMarcus Overhagen/*
204a91b97SMarcus Overhagen * MainWin.cpp - Media Player for the Haiku Operating System
304a91b97SMarcus Overhagen *
404a91b97SMarcus Overhagen * Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
58ae6dbd9SStephan Aßmus * Copyright (C) 2007-2010 Stephan A��mus <superstippi@gmx.de> (GPL->MIT ok)
69327db63SFredrik Modeen * Copyright (C) 2007-2009 Fredrik Mod��en <[FirstName]@[LastName].se> (MIT ok)
704a91b97SMarcus Overhagen *
83065fd47SAlexander von Gluck IV * Released under the terms of the MIT license.
904a91b97SMarcus Overhagen */
10c60fcc87SStephan Aßmus
11f2d247d8SAxel Dörfler
1204a91b97SMarcus Overhagen#include "MainWin.h"
1304a91b97SMarcus Overhagen
1409464bc9SStephan Aßmus#include <math.h>
1509464bc9SStephan Aßmus#include <stdio.h>
1609464bc9SStephan Aßmus#include <string.h>
1709464bc9SStephan Aßmus
1809464bc9SStephan Aßmus#include <Alert.h>
1909464bc9SStephan Aßmus#include <Application.h>
2009464bc9SStephan Aßmus#include <Autolock.h>
21238df8fbSAdrien Destugues#include <Catalog.h>
2209464bc9SStephan Aßmus#include <Debug.h>
231aa885efSAxel Dörfler#include <fs_attr.h>
2492cb0c5dSDario Casalinuovo#include <LayoutBuilder.h>
255bacae95SStephan Aßmus#include <Language.h>
26238df8fbSAdrien Destugues#include <Locale.h>
2761a59e87SDario Casalinuovo#include <MediaRoster.h>
2804a91b97SMarcus Overhagen#include <Menu.h>
2904a91b97SMarcus Overhagen#include <MenuBar.h>
3004a91b97SMarcus Overhagen#include <MenuItem.h>
31e663610eSStephan Aßmus#include <MessageRunner.h>
3204a91b97SMarcus Overhagen#include <Messenger.h>
3304a91b97SMarcus Overhagen#include <PopUpMenu.h>
34c5d6e9b0SMichael Lotz#include <PropertyInfo.h>
35658aafcbSFrançois Revol#include <RecentItems.h>
36658aafcbSFrançois Revol#include <Roster.h>
3709464bc9SStephan Aßmus#include <Screen.h>
3804a91b97SMarcus Overhagen#include <String.h>
391c1de1a5SStephan Aßmus#include <TypeConstants.h>
4009464bc9SStephan Aßmus#include <View.h>
4104a91b97SMarcus Overhagen
429282400fSStephan Aßmus#include "AudioProducer.h"
435fa5e5feSStephan Aßmus#include "ControllerObserver.h"
443a8771cfSStephan Aßmus#include "DurationToString.h"
451aa885efSAxel Dörfler#include "FilePlaylistItem.h"
4609464bc9SStephan Aßmus#include "MainApp.h"
4792cb0c5dSDario Casalinuovo#include "NetworkStreamWin.h"
489282400fSStephan Aßmus#include "PeakView.h"
49c60fcc87SStephan Aßmus#include "PlaylistItem.h"
505fa5e5feSStephan Aßmus#include "PlaylistObserver.h"
515fa5e5feSStephan Aßmus#include "PlaylistWindow.h"
529a5f768bSStephan Aßmus#include "Settings.h"
535fa5e5feSStephan Aßmus
54d75c9c3dSAxel Dörfler
55546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
56546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "MediaPlayer-Main"
5799cd5eebSMarcus Overhagen#define MIN_WIDTH 250
58e1d8d7d6SMarcus Overhagen
59399b0e8aSMarcus Overhagen
60d75c9c3dSAxel Dörflerint MainWin::sNoVideoWidth = MIN_WIDTH;
619a746385SStephan Aßmus
629a746385SStephan Aßmus
63399b0e8aSMarcus Overhagen// XXX TODO: why is lround not defined?
64399b0e8aSMarcus Overhagen#define lround(a) ((int)(0.99999 + (a)))
65399b0e8aSMarcus Overhagen
66d329f1d6SStephan Aßmusenum {
6704a91b97SMarcus Overhagen	M_DUMMY = 0x100,
68e1d8d7d6SMarcus Overhagen	M_FILE_OPEN = 0x1000,
6992cb0c5dSDario Casalinuovo	M_NETWORK_STREAM_OPEN,
70e1d8d7d6SMarcus Overhagen	M_FILE_INFO,
715fa5e5feSStephan Aßmus	M_FILE_PLAYLIST,
72e1d8d7d6SMarcus Overhagen	M_FILE_CLOSE,
73bae0154cSStephan Aßmus	M_FILE_QUIT,
741f3691dfSStephan Aßmus	M_VIEW_SIZE,
7504a91b97SMarcus Overhagen	M_TOGGLE_FULLSCREEN,
76c8e27e39SStephan Aßmus	M_TOGGLE_ALWAYS_ON_TOP,
77c8e27e39SStephan Aßmus	M_TOGGLE_NO_INTERFACE,
7804a91b97SMarcus Overhagen	M_VOLUME_UP,
7904a91b97SMarcus Overhagen	M_VOLUME_DOWN,
80540fe7aeSStephan Aßmus	M_SKIP_NEXT,
81540fe7aeSStephan Aßmus	M_SKIP_PREV,
820beac2ffSStephan Aßmus	M_WIND,
83f186fa40SStephan Aßmus
84f186fa40SStephan Aßmus	// The common display aspect ratios
85f186fa40SStephan Aßmus	M_ASPECT_SAME_AS_SOURCE,
86f186fa40SStephan Aßmus	M_ASPECT_NO_DISTORTION,
87f186fa40SStephan Aßmus	M_ASPECT_4_3,
88f186fa40SStephan Aßmus	M_ASPECT_16_9,
89f186fa40SStephan Aßmus	M_ASPECT_83_50,
90f186fa40SStephan Aßmus	M_ASPECT_7_4,
91f186fa40SStephan Aßmus	M_ASPECT_37_20,
92f186fa40SStephan Aßmus	M_ASPECT_47_20,
93f186fa40SStephan Aßmus
94c8ccdf52SStephan Aßmus	M_SELECT_AUDIO_TRACK			= 0x00000800,
95c8ccdf52SStephan Aßmus	M_SELECT_AUDIO_TRACK_END		= 0x00000fff,
96c8ccdf52SStephan Aßmus	M_SELECT_VIDEO_TRACK			= 0x00010000,
97c8ccdf52SStephan Aßmus	M_SELECT_VIDEO_TRACK_END		= 0x00010fff,
98c8ccdf52SStephan Aßmus	M_SELECT_SUB_TITLE_TRACK		= 0x00020000,
99c8ccdf52SStephan Aßmus	M_SELECT_SUB_TITLE_TRACK_END	= 0x00020fff,
1005fa5e5feSStephan Aßmus
1011c1de1a5SStephan Aßmus	M_SET_RATING,
1021c1de1a5SStephan Aßmus
1039327db63SFredrik Modeen	M_SET_PLAYLIST_POSITION,
104bae0154cSStephan Aßmus
105e663610eSStephan Aßmus	M_FILE_DELETE,
106e663610eSStephan Aßmus
10780a9df25SStephan Aßmus	M_SLIDE_CONTROLS,
10880a9df25SStephan Aßmus	M_FINISH_SLIDING_CONTROLS
10904a91b97SMarcus Overhagen};
11004a91b97SMarcus Overhagen
111c5d6e9b0SMichael Lotz
112c5d6e9b0SMichael Lotzstatic property_info sPropertyInfo[] = {
1136ba5b421SOwen	{ "Next", { B_EXECUTE_PROPERTY },
114c54e3124SAxel Dörfler		{ B_DIRECT_SPECIFIER, 0 },
1156ba5b421SOwen		"Skip to the next track.", 0
116c5d6e9b0SMichael Lotz	},
1176ba5b421SOwen	{ "Prev", { B_EXECUTE_PROPERTY },
118c54e3124SAxel Dörfler		{ B_DIRECT_SPECIFIER, 0 },
1196ba5b421SOwen		"Skip to the previous track.", 0
120c5d6e9b0SMichael Lotz	},
1216ba5b421SOwen	{ "Play", { B_EXECUTE_PROPERTY },
122238df8fbSAdrien Destugues		{ B_DIRECT_SPECIFIER, 0 },
1236ba5b421SOwen		"Start playing.", 0
124c5d6e9b0SMichael Lotz	},
1256ba5b421SOwen	{ "Stop", { B_EXECUTE_PROPERTY },
126c54e3124SAxel Dörfler		{ B_DIRECT_SPECIFIER, 0 },
1276ba5b421SOwen		"Stop playing.", 0
128c5d6e9b0SMichael Lotz	},
1296ba5b421SOwen	{ "Pause", { B_EXECUTE_PROPERTY },
130238df8fbSAdrien Destugues		{ B_DIRECT_SPECIFIER, 0 },
1316ba5b421SOwen		"Pause playback.", 0
132c5d6e9b0SMichael Lotz	},
1336ba5b421SOwen	{ "TogglePlaying", { B_EXECUTE_PROPERTY },
134c54e3124SAxel Dörfler		{ B_DIRECT_SPECIFIER, 0 },
1356ba5b421SOwen		"Toggle pause/play.", 0
136c5d6e9b0SMichael Lotz	},
1376ba5b421SOwen	{ "Mute", { B_EXECUTE_PROPERTY },
138c54e3124SAxel Dörfler		{ B_DIRECT_SPECIFIER, 0 },
1396ba5b421SOwen		"Toggle mute.", 0
140c5d6e9b0SMichael Lotz	},
1416ba5b421SOwen	{ "Volume", { B_GET_PROPERTY, B_SET_PROPERTY, 0 },
142c54e3124SAxel Dörfler		{ B_DIRECT_SPECIFIER, 0 },
1436ba5b421SOwen		"Gets/sets the volume (0.0-2.0).", 0,
144c5d6e9b0SMichael Lotz		{ B_FLOAT_TYPE }
145c5d6e9b0SMichael Lotz	},
1466ba5b421SOwen	{ "URI", { B_GET_PROPERTY, 0 },
14763bcd0d0SMichael Lotz		{ B_DIRECT_SPECIFIER, 0 },
1486ba5b421SOwen		"Gets the URI of the currently playing item.", 0,
149238df8fbSAdrien Destugues		{ B_STRING_TYPE }
15063bcd0d0SMichael Lotz	},
1516ba5b421SOwen	{ "ToggleFullscreen", { B_EXECUTE_PROPERTY },
152a16d549aSMichael Lotz		{ B_DIRECT_SPECIFIER, 0 },
1536ba5b421SOwen		"Toggle fullscreen.", 0
154a16d549aSMichael Lotz	},
1556ba5b421SOwen	{ "Duration", { B_GET_PROPERTY, 0 },
156bab9e168SMichael Lotz		{ B_DIRECT_SPECIFIER, 0 },
1576ba5b421SOwen		"Gets the duration of the currently playing item "
1586ba5b421SOwen			"in microseconds.", 0,
159bab9e168SMichael Lotz		{ B_INT64_TYPE }
160bab9e168SMichael Lotz	},
1616ba5b421SOwen	{ "Position", { B_GET_PROPERTY, B_SET_PROPERTY, 0 },
162bab9e168SMichael Lotz		{ B_DIRECT_SPECIFIER, 0 },
1636ba5b421SOwen		"Gets/sets the current playing position in microseconds.",
164bab9e168SMichael Lotz		0, { B_INT64_TYPE }
165bab9e168SMichael Lotz	},
1666ba5b421SOwen	{ "Seek", { B_SET_PROPERTY },
167bab9e168SMichael Lotz		{ B_DIRECT_SPECIFIER, 0 },
1686ba5b421SOwen		"Seek by the specified amounts of microseconds.", 0,
169bab9e168SMichael Lotz		{ B_INT64_TYPE }
170bab9e168SMichael Lotz	},
1716ba5b421SOwen	{ "PlaylistTrackCount", { B_GET_PROPERTY, 0 },
1726ba5b421SOwen		{ B_DIRECT_SPECIFIER, 0 },
1736ba5b421SOwen		"Gets the number of tracks in Playlist.", 0,
1746ba5b421SOwen		{ B_INT16_TYPE }
1756ba5b421SOwen	},
1766ba5b421SOwen	{ "PlaylistTrackTitle", { B_GET_PROPERTY, 0 },
1776ba5b421SOwen		{ B_INDEX_SPECIFIER, 0 },
1786ba5b421SOwen		"Gets the title of the nth track in Playlist.", 0,
1796ba5b421SOwen		{ B_STRING_TYPE }
1806ba5b421SOwen	},
18116af9b4cSHumdinger
18216af9b4cSHumdinger	{ 0 }
183c5d6e9b0SMichael Lotz};
184c5d6e9b0SMichael Lotz
185c5d6e9b0SMichael Lotz
1861c1de1a5SStephan Aßmusstatic const char* kRatingAttrName = "Media:Rating";
1871c1de1a5SStephan Aßmus
188238df8fbSAdrien Destuguesstatic const char* kDisabledSeekMessage = B_TRANSLATE("Drop files to play");
189fd5c3422SStephan Aßmus
190560ff447SJonas Sundströmstatic const char* kApplicationName = B_TRANSLATE_SYSTEM_NAME(NAME);
1912ee8f3f6SSiarzhuk Zharski
1921c1de1a5SStephan Aßmus
193e663610eSStephan AßmusMainWin::MainWin(bool isFirstWindow, BMessage* message)
194f2d247d8SAxel Dörfler	:
1952ee8f3f6SSiarzhuk Zharski	BWindow(BRect(100, 100, 400, 300), kApplicationName, B_TITLED_WINDOW,
196f74d4e95SAxel Dörfler 		B_ASYNCHRONOUS_CONTROLS),
197f907fa59SStephan Aßmus 	fCreationTime(system_time()),
198f2d247d8SAxel Dörfler	fInfoWin(NULL),
199f2d247d8SAxel Dörfler	fPlaylistWindow(NULL),
200f2d247d8SAxel Dörfler	fHasFile(false),
201f2d247d8SAxel Dörfler	fHasVideo(false),
202f2d247d8SAxel Dörfler	fHasAudio(false),
203f2d247d8SAxel Dörfler	fPlaylist(new Playlist),
204f2d247d8SAxel Dörfler	fPlaylistObserver(new PlaylistObserver(this)),
205f2d247d8SAxel Dörfler	fController(new Controller),
206f2d247d8SAxel Dörfler	fControllerObserver(new ControllerObserver(this,
2079a5f768bSStephan Aßmus		OBSERVE_FILE_CHANGES | OBSERVE_TRACK_CHANGES
2089a5f768bSStephan Aßmus			| OBSERVE_PLAYBACK_STATE_CHANGES | OBSERVE_POSITION_CHANGES
2099a5f768bSStephan Aßmus			| OBSERVE_VOLUME_CHANGES)),
210f2d247d8SAxel Dörfler	fIsFullscreen(false),
211f2d247d8SAxel Dörfler	fAlwaysOnTop(false),
212f2d247d8SAxel Dörfler	fNoInterface(false),
21380a9df25SStephan Aßmus	fShowsFullscreenControls(false),
214f2d247d8SAxel Dörfler	fSourceWidth(-1),
215f2d247d8SAxel Dörfler	fSourceHeight(-1),
216f2d247d8SAxel Dörfler	fWidthAspect(0),
217f2d247d8SAxel Dörfler	fHeightAspect(0),
218e663610eSStephan Aßmus	fSavedFrame(),
219e663610eSStephan Aßmus	fNoVideoFrame(),
22080a9df25SStephan Aßmus
221f2d247d8SAxel Dörfler	fMouseDownTracking(false),
22280a9df25SStephan Aßmus	fLastMousePos(0, 0),
22380a9df25SStephan Aßmus	fLastMouseMovedTime(system_time()),
22480a9df25SStephan Aßmus	fMouseMoveDist(0),
22580a9df25SStephan Aßmus
226ab18a502SStephan Aßmus	fGlobalSettingsListener(this),
2270beac2ffSStephan Aßmus	fInitialSeekPosition(0),
2280beac2ffSStephan Aßmus	fAllowWinding(true)
22904a91b97SMarcus Overhagen{
2309a746385SStephan Aßmus	// Handle window position and size depending on whether this is the
2319a746385SStephan Aßmus	// first window or not. Use the window size from the window that was
2329a746385SStephan Aßmus	// last resized by the user.
233399b0e8aSMarcus Overhagen	static int pos = 0;
234399b0e8aSMarcus Overhagen	MoveBy(pos * 25, pos * 25);
235399b0e8aSMarcus Overhagen	pos = (pos + 1) % 15;
236bae0154cSStephan Aßmus
237a178983dSAxel Dörfler	BRect frame = Settings::Default()->AudioPlayerWindowFrame();
2389a746385SStephan Aßmus	if (frame.IsValid()) {
2399a746385SStephan Aßmus		if (isFirstWindow) {
240e663610eSStephan Aßmus			if (message == NULL) {
241e663610eSStephan Aßmus				MoveTo(frame.LeftTop());
242e663610eSStephan Aßmus				ResizeTo(frame.Width(), frame.Height());
243e663610eSStephan Aßmus			} else {
244e663610eSStephan Aßmus				// Delay moving to the initial position, since we don't
245e663610eSStephan Aßmus				// know if we will be playing audio at all.
246e663610eSStephan Aßmus				message->AddRect("window frame", frame);
247e663610eSStephan Aßmus			}
248f907fa59SStephan Aßmus		}
2499a746385SStephan Aßmus		if (sNoVideoWidth == MIN_WIDTH)
2509a746385SStephan Aßmus			sNoVideoWidth = frame.IntegerWidth();
2519a746385SStephan Aßmus	} else if (sNoVideoWidth > MIN_WIDTH) {
2529a746385SStephan Aßmus		ResizeTo(sNoVideoWidth, Bounds().Height());
253f907fa59SStephan Aßmus	}
2549a746385SStephan Aßmus	fNoVideoWidth = sNoVideoWidth;
255f907fa59SStephan Aßmus
25604a91b97SMarcus Overhagen	BRect rect = Bounds();
25704a91b97SMarcus Overhagen
25804a91b97SMarcus Overhagen	// background
2591b7f76bcSStephan Aßmus	fBackground = new BView(rect, "background", B_FOLLOW_ALL,
2601b7f76bcSStephan Aßmus		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
26125fcb499SStephan Aßmus	fBackground->SetViewColor(0, 0, 0);
26204a91b97SMarcus Overhagen	AddChild(fBackground);
26304a91b97SMarcus Overhagen
26499cd5eebSMarcus Overhagen	// menu
26504a91b97SMarcus Overhagen	fMenuBar = new BMenuBar(fBackground->Bounds(), "menu");
266d329f1d6SStephan Aßmus	_CreateMenu();
26704a91b97SMarcus Overhagen	fBackground->AddChild(fMenuBar);
268cf4ef413SStephan Aßmus	fMenuBar->SetResizingMode(B_FOLLOW_NONE);
26904a91b97SMarcus Overhagen	fMenuBar->ResizeToPreferred();
2705fa5e5feSStephan Aßmus	fMenuBarWidth = (int)fMenuBar->Frame().Width() + 1;
27104a91b97SMarcus Overhagen	fMenuBarHeight = (int)fMenuBar->Frame().Height() + 1;
27204a91b97SMarcus Overhagen
27304a91b97SMarcus Overhagen	// video view
2741b7f76bcSStephan Aßmus	rect = BRect(0, fMenuBarHeight, fBackground->Bounds().right,
2751b7f76bcSStephan Aßmus		fMenuBarHeight + 10);
2760fc56ed5SStephan Aßmus	fVideoView = new VideoView(rect, "video display", B_FOLLOW_NONE);
27704a91b97SMarcus Overhagen	fBackground->AddChild(fVideoView);
278bae0154cSStephan Aßmus
27999cd5eebSMarcus Overhagen	// controls
2801b7f76bcSStephan Aßmus	rect = BRect(0, fMenuBarHeight + 11, fBackground->Bounds().right,
2811b7f76bcSStephan Aßmus		fBackground->Bounds().bottom);
2825fa5e5feSStephan Aßmus	fControls = new ControllerView(rect, fController, fPlaylist);
28399cd5eebSMarcus Overhagen	fBackground->AddChild(fControls);
28499cd5eebSMarcus Overhagen	fControls->ResizeToPreferred();
28599cd5eebSMarcus Overhagen	fControlsHeight = (int)fControls->Frame().Height() + 1;
28699cd5eebSMarcus Overhagen	fControlsWidth = (int)fControls->Frame().Width() + 1;
287aadc5f57SMarcus Overhagen	fControls->SetResizingMode(B_FOLLOW_BOTTOM | B_FOLLOW_LEFT_RIGHT);
288fd5c3422SStephan Aßmus	fControls->SetDisabledString(kDisabledSeekMessage);
2895fa5e5feSStephan Aßmus
2905fa5e5feSStephan Aßmus	fPlaylist->AddListener(fPlaylistObserver);
29199cd5eebSMarcus Overhagen	fController->SetVideoView(fVideoView);
2925fa5e5feSStephan Aßmus	fController->AddListener(fControllerObserver);
2939282400fSStephan Aßmus	PeakView* peakView = fControls->GetPeakView();
2949282400fSStephan Aßmus	peakView->SetPeakNotificationWhat(MSG_PEAK_NOTIFICATION);
2959282400fSStephan Aßmus	fController->SetPeakListener(peakView);
296bae0154cSStephan Aßmus
297d329f1d6SStephan Aßmus	_SetupWindow();
2985fa5e5feSStephan Aßmus
299bae0154cSStephan Aßmus	// setup the playlist window now, we need to have it
300cc2fbed2SStephan Aßmus	// running for the undo/redo playlist editing
3011b7f76bcSStephan Aßmus	fPlaylistWindow = new PlaylistWindow(BRect(150, 150, 500, 600), fPlaylist,
3021b7f76bcSStephan Aßmus		fController);
303cc2fbed2SStephan Aßmus	fPlaylistWindow->Hide();
304cc2fbed2SStephan Aßmus	fPlaylistWindow->Show();
305cc2fbed2SStephan Aßmus		// this makes sure the window thread is running without
306cc2fbed2SStephan Aßmus		// showing the window just yet
307cc2fbed2SStephan Aßmus
3089a5f768bSStephan Aßmus	Settings::Default()->AddListener(&fGlobalSettingsListener);
3099a5f768bSStephan Aßmus	_AdoptGlobalSettings();
3109a5f768bSStephan Aßmus
311dd091096SStephan Aßmus	AddShortcut('z', B_COMMAND_KEY, new BMessage(B_UNDO));
312dd091096SStephan Aßmus	AddShortcut('y', B_COMMAND_KEY, new BMessage(B_UNDO));
313dd091096SStephan Aßmus	AddShortcut('z', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(B_REDO));
314dd091096SStephan Aßmus	AddShortcut('y', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(B_REDO));
315e337e55fSStephan Aßmus
316e337e55fSStephan Aßmus	Hide();
317e337e55fSStephan Aßmus	Show();
318e663610eSStephan Aßmus
319e663610eSStephan Aßmus	if (message != NULL)
320e663610eSStephan Aßmus		PostMessage(message);
32161a59e87SDario Casalinuovo
32261a59e87SDario Casalinuovo	BMediaRoster* roster = BMediaRoster::Roster();
32361a59e87SDario Casalinuovo	roster->StartWatching(BMessenger(this, this), B_MEDIA_SERVER_STARTED);
32461a59e87SDario Casalinuovo	roster->StartWatching(BMessenger(this, this),  B_MEDIA_SERVER_QUIT);
32504a91b97SMarcus Overhagen}
32604a91b97SMarcus Overhagen
32704a91b97SMarcus Overhagen
32804a91b97SMarcus OverhagenMainWin::~MainWin()
32904a91b97SMarcus Overhagen{
3309327db63SFredrik Modeen//	printf("MainWin::~MainWin\n");
3315fa5e5feSStephan Aßmus
33261a59e87SDario Casalinuovo	BMediaRoster* roster = BMediaRoster::CurrentRoster();
33361a59e87SDario Casalinuovo	roster->StopWatching(BMessenger(this, this), B_MEDIA_SERVER_STARTED);
33461a59e87SDario Casalinuovo	roster->StopWatching(BMessenger(this, this), B_MEDIA_SERVER_QUIT);
33561a59e87SDario Casalinuovo
3364ddc254cSStephan Aßmus	Settings::Default()->RemoveListener(&fGlobalSettingsListener);
3375fa5e5feSStephan Aßmus	fPlaylist->RemoveListener(fPlaylistObserver);
33852a90fe6SStephan Aßmus	fController->Lock();
3395fa5e5feSStephan Aßmus	fController->RemoveListener(fControllerObserver);
3409282400fSStephan Aßmus	fController->SetPeakListener(NULL);
34152a90fe6SStephan Aßmus	fController->SetVideoTarget(NULL);
34252a90fe6SStephan Aßmus	fController->Unlock();
3435fa5e5feSStephan Aßmus
3445fa5e5feSStephan Aßmus	// give the views a chance to detach from any notifiers
3455fa5e5feSStephan Aßmus	// before we delete them
3465fa5e5feSStephan Aßmus	fBackground->RemoveSelf();
3475fa5e5feSStephan Aßmus	delete fBackground;
3485fa5e5feSStephan Aßmus
3494ddc254cSStephan Aßmus	if (fInfoWin && fInfoWin->Lock())
350c91fb637SFrançois Revol		fInfoWin->Quit();
3514ddc254cSStephan Aßmus
3524ddc254cSStephan Aßmus	if (fPlaylistWindow && fPlaylistWindow->Lock())
3535fa5e5feSStephan Aßmus		fPlaylistWindow->Quit();
354bae0154cSStephan Aßmus
3555fa5e5feSStephan Aßmus	delete fPlaylist;
35696cddcb7SJérôme Duval	fPlaylist = NULL;
3570fc56ed5SStephan Aßmus
3580fc56ed5SStephan Aßmus	// quit the Controller looper thread
3590fc56ed5SStephan Aßmus	thread_id controllerThread = fController->Thread();
3600fc56ed5SStephan Aßmus	fController->PostMessage(B_QUIT_REQUESTED);
3610fc56ed5SStephan Aßmus	status_t exitValue;
3620fc56ed5SStephan Aßmus	wait_for_thread(controllerThread, &exitValue);
363e1d8d7d6SMarcus Overhagen}
364e1d8d7d6SMarcus Overhagen
365e1d8d7d6SMarcus Overhagen
366d329f1d6SStephan Aßmus// #pragma mark -
367e1d8d7d6SMarcus Overhagen
368e1d8d7d6SMarcus Overhagen
369e1d8d7d6SMarcus Overhagenvoid
3704ddc254cSStephan AßmusMainWin::FrameResized(float newWidth, float newHeight)
371e1d8d7d6SMarcus Overhagen{
3724ddc254cSStephan Aßmus	if (newWidth != Bounds().Width() || newHeight != Bounds().Height()) {
373d329f1d6SStephan Aßmus		debugger("size wrong\n");
374d329f1d6SStephan Aßmus	}
3755fa5e5feSStephan Aßmus
376c8e27e39SStephan Aßmus	bool noMenu = fNoInterface || fIsFullscreen;
377c8e27e39SStephan Aßmus	bool noControls = fNoInterface || fIsFullscreen;
3784ddc254cSStephan Aßmus
3799327db63SFredrik Modeen//	printf("FrameResized enter: newWidth %.0f, newHeight %.0f\n",
3809327db63SFredrik Modeen//		newWidth, newHeight);
3814ddc254cSStephan Aßmus
3829a746385SStephan Aßmus	if (!fHasVideo)
3839a746385SStephan Aßmus		sNoVideoWidth = fNoVideoWidth = (int)newWidth;
3849a746385SStephan Aßmus
3854ddc254cSStephan Aßmus	int maxVideoWidth  = int(newWidth) + 1;
3864ddc254cSStephan Aßmus	int maxVideoHeight = int(newHeight) + 1
3874ddc254cSStephan Aßmus		- (noMenu  ? 0 : fMenuBarHeight)
3884ddc254cSStephan Aßmus		- (noControls ? 0 : fControlsHeight);
3894ddc254cSStephan Aßmus
3904ddc254cSStephan Aßmus	ASSERT(maxVideoHeight >= 0);
3914ddc254cSStephan Aßmus
392d329f1d6SStephan Aßmus	int y = 0;
3934ddc254cSStephan Aßmus
3944ddc254cSStephan Aßmus	if (noMenu) {
39525fcb499SStephan Aßmus		if (!fMenuBar->IsHidden(fMenuBar))
396d329f1d6SStephan Aßmus			fMenuBar->Hide();
39799cd5eebSMarcus Overhagen	} else {
398c8e27e39SStephan Aßmus		fMenuBar->MoveTo(0, y);
3994ddc254cSStephan Aßmus		fMenuBar->ResizeTo(newWidth, fMenuBarHeight - 1);
40025fcb499SStephan Aßmus		if (fMenuBar->IsHidden(fMenuBar))
401d329f1d6SStephan Aßmus			fMenuBar->Show();
402d329f1d6SStephan Aßmus		y += fMenuBarHeight;
40399cd5eebSMarcus Overhagen	}
4044ddc254cSStephan Aßmus
4054ddc254cSStephan Aßmus	if (maxVideoHeight == 0) {
40625fcb499SStephan Aßmus		if (!fVideoView->IsHidden(fVideoView))
407d329f1d6SStephan Aßmus			fVideoView->Hide();
408d329f1d6SStephan Aßmus	} else {
4094ddc254cSStephan Aßmus		_ResizeVideoView(0, y, maxVideoWidth, maxVideoHeight);
41025fcb499SStephan Aßmus		if (fVideoView->IsHidden(fVideoView))
411d329f1d6SStephan Aßmus			fVideoView->Show();
4124ddc254cSStephan Aßmus		y += maxVideoHeight;
413d329f1d6SStephan Aßmus	}
414bae0154cSStephan Aßmus
4154ddc254cSStephan Aßmus	if (noControls) {
41625fcb499SStephan Aßmus		if (!fControls->IsHidden(fControls))
417d329f1d6SStephan Aßmus			fControls->Hide();
418d329f1d6SStephan Aßmus	} else {
419d329f1d6SStephan Aßmus		fControls->MoveTo(0, y);
4204ddc254cSStephan Aßmus		fControls->ResizeTo(newWidth, fControlsHeight - 1);
42125fcb499SStephan Aßmus		if (fControls->IsHidden(fControls))
422d329f1d6SStephan Aßmus			fControls->Show();
423d329f1d6SStephan Aßmus//		y += fControlsHeight;
4245fa5e5feSStephan Aßmus	}
425d329f1d6SStephan Aßmus
4269327db63SFredrik Modeen//	printf("FrameResized leave\n");
42799cd5eebSMarcus Overhagen}
42899cd5eebSMarcus Overhagen
42999cd5eebSMarcus Overhagen
43099cd5eebSMarcus Overhagenvoid
431d75c9c3dSAxel DörflerMainWin::Zoom(BPoint /*position*/, float /*width*/, float /*height*/)
43299cd5eebSMarcus Overhagen{
433d329f1d6SStephan Aßmus	PostMessage(M_TOGGLE_FULLSCREEN);
43404a91b97SMarcus Overhagen}
43504a91b97SMarcus Overhagen
43604a91b97SMarcus Overhagen
43704a91b97SMarcus Overhagenvoid
438d75c9c3dSAxel DörflerMainWin::DispatchMessage(BMessage* msg, BHandler* handler)
43904a91b97SMarcus Overhagen{
440d329f1d6SStephan Aßmus	if ((msg->what == B_MOUSE_DOWN)
441d329f1d6SStephan Aßmus		&& (handler == fBackground || handler == fVideoView
44280a9df25SStephan Aßmus			|| handler == fControls)) {
443d329f1d6SStephan Aßmus		_MouseDown(msg, dynamic_cast<BView*>(handler));
44480a9df25SStephan Aßmus	}
44504a91b97SMarcus Overhagen
446d329f1d6SStephan Aßmus	if ((msg->what == B_MOUSE_MOVED)
447d329f1d6SStephan Aßmus		&& (handler == fBackground || handler == fVideoView
44880a9df25SStephan Aßmus			|| handler == fControls)) {
449d329f1d6SStephan Aßmus		_MouseMoved(msg, dynamic_cast<BView*>(handler));
45080a9df25SStephan Aßmus	}
45104a91b97SMarcus Overhagen
452d329f1d6SStephan Aßmus	if ((msg->what == B_MOUSE_UP)
45380a9df25SStephan Aßmus		&& (handler == fBackground || handler == fVideoView)) {
454d329f1d6SStephan Aßmus		_MouseUp(msg);
45580a9df25SStephan Aßmus	}
45604a91b97SMarcus Overhagen
457d329f1d6SStephan Aßmus	if ((msg->what == B_KEY_DOWN)
458d329f1d6SStephan Aßmus		&& (handler == fBackground || handler == fVideoView)) {
459d329f1d6SStephan Aßmus		// special case for PrintScreen key
460d329f1d6SStephan Aßmus		if (msg->FindInt32("key") == B_PRINT_KEY) {
461d329f1d6SStephan Aßmus			fVideoView->OverlayScreenshotPrepare();
462d329f1d6SStephan Aßmus			BWindow::DispatchMessage(msg, handler);
463d329f1d6SStephan Aßmus			fVideoView->OverlayScreenshotCleanup();
464d329f1d6SStephan Aßmus			return;
465d329f1d6SStephan Aßmus		}
466bae0154cSStephan Aßmus
467d329f1d6SStephan Aßmus		// every other key gets dispatched to our _KeyDown first
468f2d247d8SAxel Dörfler		if (_KeyDown(msg)) {
469d329f1d6SStephan Aßmus			// it got handled, don't pass it on
470d329f1d6SStephan Aßmus			return;
471d329f1d6SStephan Aßmus		}
472e1d8d7d6SMarcus Overhagen	}
473bae0154cSStephan Aßmus
474d329f1d6SStephan Aßmus	BWindow::DispatchMessage(msg, handler);
47504a91b97SMarcus Overhagen}
47604a91b97SMarcus Overhagen
47704a91b97SMarcus Overhagen
47804a91b97SMarcus Overhagenvoid
479ab18a502SStephan AßmusMainWin::MessageReceived(BMessage* msg)
48004a91b97SMarcus Overhagen{
481540fe7aeSStephan Aßmus//	msg->PrintToStream();
482d329f1d6SStephan Aßmus	switch (msg->what) {
483c5d6e9b0SMichael Lotz		case B_EXECUTE_PROPERTY:
484c5d6e9b0SMichael Lotz		case B_GET_PROPERTY:
485c5d6e9b0SMichael Lotz		case B_SET_PROPERTY:
486c5d6e9b0SMichael Lotz		{
487c5d6e9b0SMichael Lotz			BMessage reply(B_REPLY);
488c5d6e9b0SMichael Lotz			status_t result = B_BAD_SCRIPT_SYNTAX;
489c5d6e9b0SMichael Lotz			int32 index;
490c5d6e9b0SMichael Lotz			BMessage specifier;
491c5d6e9b0SMichael Lotz			int32 what;
492c5d6e9b0SMichael Lotz			const char* property;
493c5d6e9b0SMichael Lotz
494c5d6e9b0SMichael Lotz			if (msg->GetCurrentSpecifier(&index, &specifier, &what,
495c5d6e9b0SMichael Lotz					&property) != B_OK) {
496c5d6e9b0SMichael Lotz				return BWindow::MessageReceived(msg);
497c5d6e9b0SMichael Lotz			}
498c5d6e9b0SMichael Lotz
499c5d6e9b0SMichael Lotz			BPropertyInfo propertyInfo(sPropertyInfo);
500c5d6e9b0SMichael Lotz			switch (propertyInfo.FindMatch(msg, index, &specifier, what,
501c5d6e9b0SMichael Lotz					property)) {
502c5d6e9b0SMichael Lotz				case 0:
503c5d6e9b0SMichael Lotz					fControls->SkipForward();
504c5d6e9b0SMichael Lotz					result = B_OK;
505c5d6e9b0SMichael Lotz					break;
506c5d6e9b0SMichael Lotz
507c5d6e9b0SMichael Lotz				case 1:
508c5d6e9b0SMichael Lotz					fControls->SkipBackward();
509c5d6e9b0SMichael Lotz					result = B_OK;
510c5d6e9b0SMichael Lotz					break;
511c5d6e9b0SMichael Lotz
512c5d6e9b0SMichael Lotz				case 2:
513c5d6e9b0SMichael Lotz					fController->Play();
514c5d6e9b0SMichael Lotz					result = B_OK;
515c5d6e9b0SMichael Lotz					break;
516c5d6e9b0SMichael Lotz
517c5d6e9b0SMichael Lotz				case 3:
518c5d6e9b0SMichael Lotz					fController->Stop();
519c5d6e9b0SMichael Lotz					result = B_OK;
520c5d6e9b0SMichael Lotz					break;
521c5d6e9b0SMichael Lotz
522c5d6e9b0SMichael Lotz				case 4:
523c5d6e9b0SMichael Lotz					fController->Pause();
524c5d6e9b0SMichael Lotz					result = B_OK;
525c5d6e9b0SMichael Lotz					break;
526c5d6e9b0SMichael Lotz
527c5d6e9b0SMichael Lotz				case 5:
528c5d6e9b0SMichael Lotz					fController->TogglePlaying();
529c5d6e9b0SMichael Lotz					result = B_OK;
530c5d6e9b0SMichael Lotz					break;
531c5d6e9b0SMichael Lotz
532c5d6e9b0SMichael Lotz				case 6:
533c5d6e9b0SMichael Lotz					fController->ToggleMute();
534c5d6e9b0SMichael Lotz					result = B_OK;
535c5d6e9b0SMichael Lotz					break;
536c5d6e9b0SMichael Lotz
537c5d6e9b0SMichael Lotz				case 7:
538c5d6e9b0SMichael Lotz				{
539c5d6e9b0SMichael Lotz					if (msg->what == B_GET_PROPERTY) {
540c5d6e9b0SMichael Lotz						result = reply.AddFloat("result",
541c5d6e9b0SMichael Lotz							fController->Volume());
542c5d6e9b0SMichael Lotz					} else if (msg->what == B_SET_PROPERTY) {
543c5d6e9b0SMichael Lotz						float newVolume;
544c5d6e9b0SMichael Lotz						result = msg->FindFloat("data", &newVolume);
545c5d6e9b0SMichael Lotz						if (result == B_OK)
546c5d6e9b0SMichael Lotz							fController->SetVolume(newVolume);
547c5d6e9b0SMichael Lotz					}
548c5d6e9b0SMichael Lotz					break;
549c5d6e9b0SMichael Lotz				}
550c5d6e9b0SMichael Lotz
55163bcd0d0SMichael Lotz				case 8:
55263bcd0d0SMichael Lotz				{
55363bcd0d0SMichael Lotz					if (msg->what == B_GET_PROPERTY) {
554382a4b12SMichael Lotz						BAutolock _(fPlaylist);
55563bcd0d0SMichael Lotz						const PlaylistItem* item = fController->Item();
55663bcd0d0SMichael Lotz						if (item == NULL) {
55763bcd0d0SMichael Lotz							result = B_NO_INIT;
55863bcd0d0SMichael Lotz							break;
55963bcd0d0SMichael Lotz						}
56063bcd0d0SMichael Lotz
56163bcd0d0SMichael Lotz						result = reply.AddString("result", item->LocationURI());
56263bcd0d0SMichael Lotz					}
56363bcd0d0SMichael Lotz					break;
56463bcd0d0SMichael Lotz				}
56563bcd0d0SMichael Lotz
566a16d549aSMichael Lotz				case 9:
567a16d549aSMichael Lotz					PostMessage(M_TOGGLE_FULLSCREEN);
568a16d549aSMichael Lotz					break;
569a16d549aSMichael Lotz
570bab9e168SMichael Lotz				case 10:
571bab9e168SMichael Lotz					if (msg->what != B_GET_PROPERTY)
572bab9e168SMichael Lotz						break;
573bab9e168SMichael Lotz
574bab9e168SMichael Lotz					result = reply.AddInt64("result",
575bab9e168SMichael Lotz						fController->TimeDuration());
576bab9e168SMichael Lotz					break;
577bab9e168SMichael Lotz
578bab9e168SMichael Lotz				case 11:
579bab9e168SMichael Lotz				{
580bab9e168SMichael Lotz					if (msg->what == B_GET_PROPERTY) {
581bab9e168SMichael Lotz						result = reply.AddInt64("result",
582bab9e168SMichael Lotz							fController->TimePosition());
583bab9e168SMichael Lotz					} else if (msg->what == B_SET_PROPERTY) {
584bab9e168SMichael Lotz						int64 newTime;
585bab9e168SMichael Lotz						result = msg->FindInt64("data", &newTime);
586bab9e168SMichael Lotz						if (result == B_OK)
587bab9e168SMichael Lotz							fController->SetTimePosition(newTime);
588bab9e168SMichael Lotz					}
589bab9e168SMichael Lotz
590bab9e168SMichael Lotz					break;
591bab9e168SMichael Lotz				}
592bab9e168SMichael Lotz
593bab9e168SMichael Lotz				case 12:
594bab9e168SMichael Lotz				{
595bab9e168SMichael Lotz					if (msg->what != B_SET_PROPERTY)
596bab9e168SMichael Lotz						break;
597bab9e168SMichael Lotz
598bab9e168SMichael Lotz					bigtime_t seekBy;
599bab9e168SMichael Lotz					result = msg->FindInt64("data", &seekBy);
600bab9e168SMichael Lotz					if (result != B_OK)
601bab9e168SMichael Lotz						break;
602bab9e168SMichael Lotz
603bab9e168SMichael Lotz					_Wind(seekBy, 0);
604bab9e168SMichael Lotz					break;
605bab9e168SMichael Lotz				}
606bab9e168SMichael Lotz
6076ba5b421SOwen				case 13:
6086ba5b421SOwen					result = reply.AddInt16("result", fPlaylist->CountItems());
6096ba5b421SOwen					break;
6106ba5b421SOwen
6116ba5b421SOwen				case 14:
6126ba5b421SOwen				{
6136ba5b421SOwen					int32 i = specifier.GetInt32("index", 0);
6146ba5b421SOwen					if (i >= fPlaylist->CountItems()) {
6156ba5b421SOwen						result = B_NO_INIT;
6166ba5b421SOwen						break;
6176ba5b421SOwen					}
6186ba5b421SOwen
6196ba5b421SOwen					BAutolock _(fPlaylist);
6206ba5b421SOwen					const PlaylistItem* item = fPlaylist->ItemAt(i);
6216ba5b421SOwen					result = item == NULL ? B_NO_INIT
6226ba5b421SOwen						: reply.AddString("result", item->Title());
6236ba5b421SOwen					break;
6246ba5b421SOwen				}
6256ba5b421SOwen
626c5d6e9b0SMichael Lotz				default:
627c5d6e9b0SMichael Lotz					return BWindow::MessageReceived(msg);
628c5d6e9b0SMichael Lotz			}
629c5d6e9b0SMichael Lotz
630c5d6e9b0SMichael Lotz			if (result != B_OK) {
631c5d6e9b0SMichael Lotz				reply.what = B_MESSAGE_NOT_UNDERSTOOD;
632c5d6e9b0SMichael Lotz				reply.AddString("message", strerror(result));
633c5d6e9b0SMichael Lotz				reply.AddInt32("error", result);
634c5d6e9b0SMichael Lotz			}
635c5d6e9b0SMichael Lotz
636c5d6e9b0SMichael Lotz			msg->SendReply(&reply);
637c5d6e9b0SMichael Lotz			break;
638c5d6e9b0SMichael Lotz		}
639c5d6e9b0SMichael Lotz
640