sync with linuxport @ 18013
[xbmc:xbmc-antiquated.git] / xbmc / MediaManager.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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
19  *
20  */
21
22 #include "stdafx.h"
23 #include "MediaManager.h"
24 #include "xbox/IoSupport.h"
25 #include "URL.h"
26 #include "Util.h"
27 #ifdef _LINUX
28 #include "LinuxFileSystem.h"
29 #endif
30
31 using namespace std;
32
33 const char MEDIA_SOURCES_XML[] = { "special://profile/mediasources.xml" };
34
35 class CMediaManager g_mediaManager;
36
37 CMediaManager::CMediaManager()
38 {
39 }
40
41 bool CMediaManager::LoadSources()
42 {
43   // clear our location list
44   m_locations.clear();
45
46   // load xml file...
47   TiXmlDocument xmlDoc;
48   if ( !xmlDoc.LoadFile( MEDIA_SOURCES_XML ) )
49     return false;
50
51   TiXmlElement* pRootElement = xmlDoc.RootElement();
52   if ( !pRootElement || strcmpi(pRootElement->Value(), "mediasources") != 0)
53   {
54     CLog::Log(LOGERROR, "Error loading %s, Line %d (%s)", MEDIA_SOURCES_XML, xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
55     return false;
56   }
57
58   // load the <network> block
59   TiXmlNode *pNetwork = pRootElement->FirstChild("network");
60   if (pNetwork)
61   {
62     TiXmlElement *pLocation = pNetwork->FirstChildElement("location");
63     while (pLocation)
64     {
65       CNetworkLocation location;
66       pLocation->Attribute("id", &location.id);
67       if (pLocation->FirstChild())
68       {
69         location.path = pLocation->FirstChild()->Value();
70         m_locations.push_back(location);
71       }
72       pLocation = pLocation->NextSiblingElement("location");
73     }
74   }
75   return true;
76 }
77
78 bool CMediaManager::SaveSources()
79 {
80   TiXmlDocument xmlDoc;
81   TiXmlElement xmlRootElement("mediasources");
82   TiXmlNode *pRoot = xmlDoc.InsertEndChild(xmlRootElement);
83   if (!pRoot) return false;
84
85   TiXmlElement networkNode("network");
86   TiXmlNode *pNetworkNode = pRoot->InsertEndChild(networkNode);
87   if (pNetworkNode)
88   {
89     for (vector<CNetworkLocation>::iterator it = m_locations.begin(); it != m_locations.end(); it++)
90     {
91       TiXmlElement locationNode("location");
92       locationNode.SetAttribute("id", (*it).id);
93       TiXmlText value((*it).path);
94       locationNode.InsertEndChild(value);
95       pNetworkNode->InsertEndChild(locationNode);
96     }
97   }
98   return xmlDoc.SaveFile(MEDIA_SOURCES_XML);
99 }
100
101 void CMediaManager::GetLocalDrives(VECSOURCES &localDrives, bool includeQ)
102 {
103
104 #ifdef _WIN32PC
105   CMediaSource share;
106   if (includeQ)
107   {
108     CMediaSource share;
109     share.strPath = "special://xbmc/";
110     share.strName.Format(g_localizeStrings.Get(21438),'Q');
111     share.m_ignore = true;
112     localDrives.push_back(share) ;
113   }
114
115   char* pcBuffer= NULL;
116   DWORD dwStrLength= GetLogicalDriveStrings( 0, pcBuffer );
117   if( dwStrLength != 0 )
118   {
119     dwStrLength+= 1; 
120     pcBuffer= new char [dwStrLength];
121     GetLogicalDriveStrings( dwStrLength, pcBuffer );
122     
123     UINT uDriveType; 
124     int iPos= 0, nResult; 
125     char cVolumeName[100];
126     do{
127       cVolumeName[0]= '\0';
128       uDriveType= GetDriveType( pcBuffer + iPos  );
129       if(uDriveType != DRIVE_REMOVABLE)
130         nResult= GetVolumeInformation( pcBuffer + iPos, cVolumeName, 100, 0, 0, 0, NULL, 25);
131       share.strPath= share.strName= "";
132       
133       bool bUseDCD= false; // just for testing
134       if( uDriveType > DRIVE_UNKNOWN && uDriveType == DRIVE_FIXED || uDriveType == DRIVE_REMOTE ||
135           uDriveType == DRIVE_CDROM || uDriveType == DRIVE_REMOVABLE )
136       {
137         share.strPath= pcBuffer + iPos;
138         if( cVolumeName[0] != '\0' ) share.strName= cVolumeName;
139         if( uDriveType == DRIVE_CDROM && nResult)
140         {
141           share.strName.Format( "%s %s (%s)", 
142             share.strPath, g_localizeStrings.Get(218),share.strName );
143           share.m_iDriveType= CMediaSource::SOURCE_TYPE_LOCAL;
144           bUseDCD= true;
145         }
146         else 
147         {
148           // Lets show it, like Windows explorer do... TODO: sorting should depend on driver letter
149           switch(uDriveType)
150           {
151           case DRIVE_CDROM:
152             share.strName.Format( "%s %s", share.strPath, g_localizeStrings.Get(218));
153             break;
154           case DRIVE_REMOVABLE:
155             if(share.strName.IsEmpty())
156               share.strName.Format( "%s %s", share.strPath, g_localizeStrings.Get(437));
157             break;
158           case DRIVE_UNKNOWN:
159             share.strName.Format( "%s %s", share.strPath, g_localizeStrings.Get(13205));
160             break;
161           default:
162             share.strName.Format( "%s %s", share.strPath, share.strName);
163             break;
164           }
165         }
166         share.strName.Replace(":\\",":");
167         share.m_ignore= true;
168         if( !bUseDCD )
169         {
170           share.m_iDriveType= ( 
171            ( uDriveType == DRIVE_FIXED  )    ? CMediaSource::SOURCE_TYPE_LOCAL :
172            ( uDriveType == DRIVE_REMOTE )    ? CMediaSource::SOURCE_TYPE_REMOTE :
173            ( uDriveType == DRIVE_CDROM  )    ? CMediaSource::SOURCE_TYPE_DVD :
174            ( uDriveType == DRIVE_REMOVABLE ) ? CMediaSource::SOURCE_TYPE_REMOVABLE :
175              CMediaSource::SOURCE_TYPE_UNKNOWN );
176         }
177
178         localDrives.push_back(share);
179       }
180       iPos += (strlen( pcBuffer + iPos) + 1 );
181     } while( strlen( pcBuffer + iPos ) > 0 );
182   }
183   delete[] pcBuffer;
184 #else
185 #ifndef _LINUX
186   // Local shares
187   CMediaSource share;
188   share.strPath = "C:\\";
189   share.strName.Format(g_localizeStrings.Get(21438),'C');
190   share.m_ignore = true;
191   share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
192   localDrives.push_back(share);
193 #endif
194
195 #ifdef _LINUX
196   // Home directory
197   CMediaSource share;
198   share.strPath = getenv("HOME");
199   share.strName = g_localizeStrings.Get(21440);
200   share.m_ignore = true;
201   share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
202   localDrives.push_back(share);
203 #endif
204
205   share.strPath = "D:\\";
206   share.strName = g_localizeStrings.Get(218);
207   share.m_iDriveType = CMediaSource::SOURCE_TYPE_DVD;
208   localDrives.push_back(share);
209
210   share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
211 #ifndef _LINUX
212   share.strPath = "E:\\";
213   share.strName.Format(g_localizeStrings.Get(21438),'E');
214   localDrives.push_back(share);
215   for (char driveletter=EXTEND_DRIVE_BEGIN; driveletter<=EXTEND_DRIVE_END; driveletter++)
216   {
217     if (CIoSupport::DriveExists(driveletter))
218     {
219       CMediaSource share;
220       share.strPath.Format("%c:\\", driveletter);
221       share.strName.Format(g_localizeStrings.Get(21438),driveletter);
222       share.m_ignore = true;
223       localDrives.push_back(share);
224     }
225   }
226   if (includeQ)
227   {
228     CMediaSource share;
229     share.strPath = "special://xbmc/";
230     share.strName.Format(g_localizeStrings.Get(21438),'Q');
231     share.m_ignore = true;
232     localDrives.push_back(share) ;
233   }
234 #endif
235
236 #ifdef _LINUX
237   CLinuxFileSystem::GetLocalDrives(localDrives);
238 #endif
239 #endif
240 }
241
242 void CMediaManager::GetNetworkLocations(VECSOURCES &locations)
243 {
244   // Load our xml file
245   LoadSources();
246   for (unsigned int i = 0; i < m_locations.size(); i++)
247   {
248     CMediaSource share;
249     share.strPath = m_locations[i].path;
250     CURL url(share.strPath);
251     url.GetURLWithoutUserDetails(share.strName);
252     locations.push_back(share);
253   }
254 }
255
256 bool CMediaManager::AddNetworkLocation(const CStdString &path)
257 {
258   CNetworkLocation location;
259   location.path = path;
260   location.id = (int)m_locations.size();
261   m_locations.push_back(location);
262   return SaveSources();
263 }
264
265 bool CMediaManager::HasLocation(const CStdString& path) const
266 {
267   for (unsigned int i=0;i<m_locations.size();++i)
268   {
269     if (m_locations[i].path == path)
270       return true;
271   }
272
273   return false;
274 }
275
276
277 bool CMediaManager::RemoveLocation(const CStdString& path)
278 {
279   for (unsigned int i=0;i<m_locations.size();++i)
280   {
281     if (m_locations[i].path == path)
282     {
283       // prompt for sources, remove, cancel,
284       m_locations.erase(m_locations.begin()+i);
285       return SaveSources();
286     }
287   }
288
289   return false;
290 }
291
292 bool CMediaManager::SetLocationPath(const CStdString& oldPath, const CStdString& newPath)
293 {
294   for (unsigned int i=0;i<m_locations.size();++i)
295   {
296     if (m_locations[i].path == oldPath)
297     {
298       m_locations[i].path = newPath;
299       return SaveSources();
300     }
301   }
302
303   return false;
304 }
305