2 * Copyright (C) 2005-2008 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "GUIDialogMediaSource.h"
23 #include "GUIDialogKeyboard.h"
24 #include "GUIDialogFileBrowser.h"
25 #include "video/windows/GUIWindowVideoBase.h"
26 #include "video/dialogs/GUIDialogVideoScan.h"
27 #include "guilib/GUIWindowManager.h"
29 #include "utils/URIUtils.h"
30 #include "filesystem/Directory.h"
31 #include "GUIDialogYesNo.h"
33 #include "settings/Settings.h"
34 #include "settings/GUISettings.h"
35 #include "guilib/LocalizeStrings.h"
38 using namespace XFILE;
40 #define CONTROL_HEADING 2
41 #define CONTROL_PATH 10
42 #define CONTROL_PATH_BROWSE 11
43 #define CONTROL_NAME 12
44 #define CONTROL_PATH_ADD 13
45 #define CONTROL_PATH_REMOVE 14
47 #define CONTROL_CANCEL 19
48 #define CONTROL_CONTENT 20
50 CGUIDialogMediaSource::CGUIDialogMediaSource(void)
51 : CGUIDialog(WINDOW_DIALOG_MEDIA_SOURCE, "DialogMediaSource.xml")
53 m_paths = new CFileItemList;
56 CGUIDialogMediaSource::~CGUIDialogMediaSource()
61 bool CGUIDialogMediaSource::OnBack(int actionID)
64 return CGUIDialog::OnBack(actionID);
67 bool CGUIDialogMediaSource::OnMessage(CGUIMessage& message)
69 switch ( message.GetMessage() )
73 int iControl = message.GetSenderId();
74 int iAction = message.GetParam1();
75 if (iControl == CONTROL_PATH && (iAction == ACTION_SELECT_ITEM || iAction == ACTION_MOUSE_LEFT_CLICK))
76 OnPath(GetSelectedItem());
77 else if (iControl == CONTROL_PATH_BROWSE)
78 OnPathBrowse(GetSelectedItem());
79 else if (iControl == CONTROL_PATH_ADD)
81 else if (iControl == CONTROL_PATH_REMOVE)
82 OnPathRemove(GetSelectedItem());
83 else if (iControl == CONTROL_NAME)
85 OnEditChanged(iControl, m_name);
88 else if (iControl == CONTROL_OK)
90 else if (iControl == CONTROL_CANCEL)
95 case GUI_MSG_WINDOW_INIT:
103 case GUI_MSG_SETFOCUS:
104 if (message.GetControlId() == CONTROL_PATH_BROWSE ||
105 message.GetControlId() == CONTROL_PATH_ADD ||
106 message.GetControlId() == CONTROL_PATH_REMOVE)
108 HighlightItem(GetSelectedItem());
114 return CGUIDialog::OnMessage(message);
117 // \brief Show CGUIDialogMediaSource dialog and prompt for a new media source.
118 // \return True if the media source is added, false otherwise.
119 bool CGUIDialogMediaSource::ShowAndAddMediaSource(const CStdString &type)
121 CGUIDialogMediaSource *dialog = (CGUIDialogMediaSource *)g_windowManager.GetWindow(WINDOW_DIALOG_MEDIA_SOURCE);
122 if (!dialog) return false;
123 dialog->Initialize();
124 dialog->SetShare(CMediaSource());
125 dialog->SetTypeOfMedia(type);
127 bool confirmed(dialog->IsConfirmed());
129 { // yay, add this share
132 bool bConfirmed=false;
133 VECSOURCES* pShares = g_settings.GetSourcesFromType(type);
134 CStdString strName = dialog->m_name;
137 for (i=0;i<pShares->size();++i)
139 if ((*pShares)[i].strName.Equals(strName))
142 if (i < pShares->size()) // found a match - try next
143 strName.Format("%s (%i)",dialog->m_name,j++);
147 share.FromNameAndPaths(type, strName, dialog->GetPaths());
148 if (dialog->m_paths->Size() > 0) {
149 share.m_strThumbnailImage = dialog->m_paths->Get(0)->GetThumbnailImage();
151 g_settings.AddShare(type, share);
155 if (dialog->m_bRunScan)
157 CGUIDialogVideoScan* scanner = (CGUIDialogVideoScan*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
159 scanner->StartScanning(share.strPath, true);
163 dialog->m_paths->Clear();
167 bool CGUIDialogMediaSource::ShowAndEditMediaSource(const CStdString &type, const CStdString&share)
169 VECSOURCES* pShares=NULL;
173 for (unsigned int i=0;i<pShares->size();++i)
175 if ((*pShares)[i].strName.Equals(share))
176 return ShowAndEditMediaSource(type,(*pShares)[i]);
183 bool CGUIDialogMediaSource::ShowAndEditMediaSource(const CStdString &type, const CMediaSource &share)
185 CStdString strOldName = share.strName;
186 CGUIDialogMediaSource *dialog = (CGUIDialogMediaSource *)g_windowManager.GetWindow(WINDOW_DIALOG_MEDIA_SOURCE);
187 if (!dialog) return false;
188 dialog->Initialize();
189 dialog->SetShare(share);
190 dialog->SetTypeOfMedia(type, true);
192 bool confirmed(dialog->IsConfirmed());
194 { // yay, add this share
196 bool bConfirmed=false;
197 VECSOURCES* pShares = g_settings.GetSourcesFromType(type);
198 CStdString strName = dialog->m_name;
201 for (i=0;i<pShares->size();++i)
203 if ((*pShares)[i].strName.Equals(strName))
206 if (i < pShares->size() && (*pShares)[i].strName != strOldName) // found a match - try next
207 strName.Format("%s (%i)",dialog->m_name,j++);
212 CMediaSource newShare;
213 newShare.FromNameAndPaths(type, strName, dialog->GetPaths());
214 g_settings.UpdateShare(type, strOldName, newShare);
216 dialog->m_paths->Clear();
220 void CGUIDialogMediaSource::OnPathBrowse(int item)
222 if (item < 0 || item > m_paths->Size()) return;
223 // Browse is called. Open the filebrowser dialog.
224 // Ignore current path is best at this stage??
226 bool allowNetworkShares(m_type != "programs");
227 VECSOURCES extraShares;
229 if (m_name != CUtil::GetTitleFromPath(m_paths->Get(item)->GetPath()))
232 if (m_type == "music")
233 { // add the music playlist location
235 share1.strPath = "special://musicplaylists/";
236 share1.strName = g_localizeStrings.Get(20011);
237 share1.m_ignore = true;
238 extraShares.push_back(share1);
240 #ifdef HAS_FILESYSTEM_SMB
241 share1.strPath = "smb://";
242 share1.strName = g_localizeStrings.Get(20171);
243 extraShares.push_back(share1);
246 #ifdef HAS_FILESYSTEM_NFS
247 share1.strPath = "nfs://";
248 share1.strName = g_localizeStrings.Get(20259);
249 extraShares.push_back(share1);
250 #endif// HAS_FILESYSTEM_NFS
252 share1.strPath = "upnp://";
253 share1.strName = "UPnP Devices";
254 extraShares.push_back(share1);
256 share1.strPath = "sap://";
257 share1.strName = "SAP Streams";
258 extraShares.push_back(share1);
260 share1.strPath = "zeroconf://";
261 share1.strName = "Zeroconf Browser";
262 extraShares.push_back(share1);
264 if (g_guiSettings.GetString("audiocds.recordingpath",false) != "")
266 share1.strPath = "special://recordings/";
267 share1.strName = g_localizeStrings.Get(21883);
268 extraShares.push_back(share1);
271 if (g_guiSettings.GetString("scrobbler.lastfmusername") != "")
273 share1.strName = "Last.FM";
274 share1.strPath = "lastfm://";
275 extraShares.push_back(share1);
278 else if (m_type == "video")
279 { // add the music playlist location
281 share1.m_ignore = true;
282 share1.strPath = "special://videoplaylists/";
283 share1.strName = g_localizeStrings.Get(20012);
284 extraShares.push_back(share1);
286 share1.strPath = "rtv://*/";
287 share1.strName = "ReplayTV Devices";
288 extraShares.push_back(share1);
290 #ifdef HAS_FILESYSTEM_SMB
291 share1.strPath = "smb://";
292 share1.strName = g_localizeStrings.Get(20171);
293 extraShares.push_back(share1);
296 #ifdef HAS_FILESYSTEM_NFS
297 share1.strPath = "nfs://";
298 share1.strName = g_localizeStrings.Get(20259);
299 extraShares.push_back(share1);
300 #endif// HAS_FILESYSTEM_NFS
302 share1.strPath = "hdhomerun://";
303 share1.strName = "HDHomerun Devices";
304 extraShares.push_back(share1);
306 share1.strPath = "sap://";
307 share1.strName = "SAP Streams";
308 extraShares.push_back(share1);
310 share1.strPath = "upnp://";
311 share1.strName = "UPnP Devices";
312 extraShares.push_back(share1);
314 share1.strPath = "zeroconf://";
315 share1.strName = "Zeroconf Browser";
316 extraShares.push_back(share1);
318 else if (m_type == "pictures")
321 share1.m_ignore = true;
322 if (g_guiSettings.GetString("debug.screenshotpath",false)!= "")
324 share1.strPath = "special://screenshots/";
325 share1.strName = g_localizeStrings.Get(20008);
326 extraShares.push_back(share1);
329 #ifdef HAS_FILESYSTEM_SMB
330 share1.strPath = "smb://";
331 share1.strName = g_localizeStrings.Get(20171);
332 extraShares.push_back(share1);
335 #ifdef HAS_FILESYSTEM_NFS
336 share1.strPath = "nfs://";
337 share1.strName = g_localizeStrings.Get(20259);
338 extraShares.push_back(share1);
339 #endif// HAS_FILESYSTEM_NFS
341 share1.strPath = "upnp://";
342 share1.strName = "UPnP Devices";
343 extraShares.push_back(share1);
345 share1.strPath = "zeroconf://";
346 share1.strName = "Zeroconf Browser";
347 extraShares.push_back(share1);
349 else if (m_type == "programs")
353 if (CGUIDialogFileBrowser::ShowAndGetSource(path, allowNetworkShares, extraShares.size()==0?NULL:&extraShares))
355 if (item < m_paths->Size()) // if the skin does funky things, m_paths may have been cleared
356 m_paths->Get(item)->SetPath(path);
357 if (!m_bNameChanged || m_name.IsEmpty())
360 m_name = url.GetWithoutUserDetails();
361 URIUtils::RemoveSlashAtEnd(m_name);
362 m_name = CUtil::GetTitleFromPath(m_name);
368 void CGUIDialogMediaSource::OnPath(int item)
370 if (item < 0 || item > m_paths->Size()) return;
372 if (m_name != CUtil::GetTitleFromPath(m_paths->Get(item)->GetPath()))
375 CStdString path(m_paths->Get(item)->GetPath());
376 CGUIDialogKeyboard::ShowAndGetInput(path, g_localizeStrings.Get(1021), false);
377 URIUtils::AddSlashAtEnd(path);
378 m_paths->Get(item)->SetPath(path);
380 if (!m_bNameChanged || m_name.IsEmpty())
382 CURL url(m_paths->Get(item)->GetPath());
383 m_name = url.GetWithoutUserDetails();
384 URIUtils::RemoveSlashAtEnd(m_name);
385 m_name = CUtil::GetTitleFromPath(m_name);
390 void CGUIDialogMediaSource::OnOK()
392 // verify the path by doing a GetDirectory.
396 share.FromNameAndPaths(m_type, m_name, GetPaths());
397 // hack: Need to temporarily add the share, then get path, then remove share
398 VECSOURCES *shares = g_settings.GetSourcesFromType(m_type);
400 shares->push_back(share);
401 if (share.strPath.Left(9).Equals("plugin://") || CDirectory::GetDirectory(share.strPath, items, "", false, true) || CGUIDialogYesNo::ShowAndGetInput(1001,1025,1003,1004))
405 if (m_type == "video" && !URIUtils::IsLiveTV(share.strPath) &&
406 !share.strPath.Left(6).Equals("rss://"))
408 CGUIWindowVideoBase::OnAssignContent(share.strPath, 0, m_info, m_settings);
412 // and remove the share again
414 shares->erase(--shares->end());
417 void CGUIDialogMediaSource::OnCancel()
423 void CGUIDialogMediaSource::UpdateButtons()
425 if (!m_paths->Size()) // sanity
428 CONTROL_ENABLE_ON_CONDITION(CONTROL_OK, !m_paths->Get(0)->GetPath().IsEmpty() && !m_name.IsEmpty());
429 CONTROL_ENABLE_ON_CONDITION(CONTROL_PATH_REMOVE, m_paths->Size() > 1);
431 SET_CONTROL_LABEL2(CONTROL_NAME, m_name);
432 SendMessage(GUI_MSG_SET_TYPE, CONTROL_NAME, 0, 1022);
434 int currentItem = GetSelectedItem();
435 SendMessage(GUI_MSG_LABEL_RESET, CONTROL_PATH);
436 for (int i = 0; i < m_paths->Size(); i++)
438 CFileItemPtr item = m_paths->Get(i);
440 CURL url(item->GetPath());
441 path = url.GetWithoutUserDetails();
442 if (path.IsEmpty()) path = "<"+g_localizeStrings.Get(231)+">"; // <None>
443 item->SetLabel(path);
445 CGUIMessage msg(GUI_MSG_LABEL_BIND, GetID(), CONTROL_PATH, 0, 0, m_paths);
447 SendMessage(GUI_MSG_ITEM_SELECT, CONTROL_PATH, currentItem);
449 SET_CONTROL_HIDDEN(CONTROL_CONTENT);
452 void CGUIDialogMediaSource::SetShare(const CMediaSource &share)
455 for (unsigned int i = 0; i < share.vecPaths.size(); i++)
457 CFileItemPtr item(new CFileItem(share.vecPaths[i], true));
460 if (0 == share.vecPaths.size())
462 CFileItemPtr item(new CFileItem("", true));
465 m_name = share.strName;
469 void CGUIDialogMediaSource::SetTypeOfMedia(const CStdString &type, bool editNotAdd)
472 int typeStringID = -1;
474 typeStringID = 249; // "Music"
475 else if (type == "video")
476 typeStringID = 291; // "Video"
477 else if (type == "programs")
478 typeStringID = 350; // "Programs"
479 else if (type == "pictures")
480 typeStringID = 1213; // "Pictures"
481 else // if (type == "files");
482 typeStringID = 744; // "Files"
484 format.Format(g_localizeStrings.Get(editNotAdd ? 1028 : 1020).c_str(), g_localizeStrings.Get(typeStringID).c_str());
485 SET_CONTROL_LABEL(CONTROL_HEADING, format);
488 void CGUIDialogMediaSource::OnWindowLoaded()
490 CGUIDialog::OnWindowLoaded();
491 ChangeButtonToEdit(CONTROL_NAME, true); // true for single label
494 int CGUIDialogMediaSource::GetSelectedItem()
496 CGUIMessage message(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_PATH);
498 int value = message.GetParam1();
499 if (value < 0 || value > m_paths->Size()) return 0;
503 void CGUIDialogMediaSource::HighlightItem(int item)
505 for (int i = 0; i < m_paths->Size(); i++)
506 m_paths->Get(i)->Select(false);
507 if (item >= 0 && item < m_paths->Size())
508 m_paths->Get(item)->Select(true);
509 CGUIMessage msg(GUI_MSG_ITEM_SELECT, GetID(), CONTROL_PATH, item);
513 void CGUIDialogMediaSource::OnPathRemove(int item)
515 m_paths->Remove(item);
517 if (item >= m_paths->Size())
518 HighlightItem(m_paths->Size() - 1);
521 if (m_paths->Size() <= 1)
523 SET_CONTROL_FOCUS(CONTROL_PATH_ADD, 0);
527 void CGUIDialogMediaSource::OnPathAdd()
529 // add a new item and select it as well
530 CFileItemPtr item(new CFileItem("", true));
533 HighlightItem(m_paths->Size() - 1);
536 vector<CStdString> CGUIDialogMediaSource::GetPaths()
538 vector<CStdString> paths;
539 for (int i = 0; i < m_paths->Size(); i++)
540 if (!m_paths->Get(i)->GetPath().IsEmpty())
541 paths.push_back(m_paths->Get(i)->GetPath());