File indexing completed on 2025-01-05 03:52:08
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2012-05-28 0007 * Description : Media server manager 0008 * 0009 * SPDX-FileCopyrightText: 2012 by Smit Mehta <smit dot meh at gmail dot com> 0010 * SPDX-FileCopyrightText: 2012-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "dmediaservermngr.h" 0017 0018 // Qt includes 0019 0020 #include <QApplication> 0021 #include <QStringList> 0022 #include <QUrl> 0023 #include <QFile> 0024 #include <QDomDocument> 0025 #include <QDomElement> 0026 #include <QTextStream> 0027 #include <QStandardPaths> 0028 0029 #if QT_VERSION < QT_VERSION_CHECK(6,0,0) 0030 # include <QTextCodec> 0031 #endif 0032 0033 // KDE includes 0034 0035 #include <klocalizedstring.h> 0036 #include <ksharedconfig.h> 0037 #include <kconfiggroup.h> 0038 0039 // Local includes 0040 0041 #include "digikam_debug.h" 0042 #include "dnotificationwrapper.h" 0043 0044 using namespace Digikam; 0045 0046 namespace DigikamGenericMediaServerPlugin 0047 { 0048 0049 class Q_DECL_HIDDEN DMediaServerMngrCreator 0050 { 0051 public: 0052 0053 DMediaServerMngr object; 0054 }; 0055 0056 Q_GLOBAL_STATIC(DMediaServerMngrCreator, creator) 0057 0058 // --------------------------------------------------------------------------------------------- 0059 0060 class Q_DECL_HIDDEN DMediaServerMngr::Private 0061 { 0062 public: 0063 0064 explicit Private() 0065 : server(nullptr) 0066 { 0067 } 0068 0069 /// Configuration XML file to store albums map to share in case of restoring between sessions. 0070 QString mapsConf; 0071 0072 /// Server instance pointer. 0073 DMediaServer* server; 0074 0075 /// The current albums collection to share. 0076 MediaServerMap collectionMap; 0077 0078 static const QString configGroupName; 0079 static const QString configStartServerOnStartupEntry; 0080 }; 0081 0082 const QString DMediaServerMngr::Private::configGroupName(QLatin1String("DLNA Settings")); 0083 const QString DMediaServerMngr::Private::configStartServerOnStartupEntry(QLatin1String("Start MediaServer At Startup")); 0084 0085 DMediaServerMngr* DMediaServerMngr::instance() 0086 { 0087 return &creator->object; 0088 } 0089 0090 DMediaServerMngr::DMediaServerMngr() 0091 : d(new Private) 0092 { 0093 d->mapsConf = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + 0094 QLatin1String("/mediaserver.xml"); 0095 } 0096 0097 DMediaServerMngr::~DMediaServerMngr() 0098 { 0099 delete d; 0100 } 0101 0102 QString DMediaServerMngr::configGroupName() const 0103 { 0104 return d->configGroupName; 0105 } 0106 0107 QString DMediaServerMngr::configStartServerOnStartupEntry() const 0108 { 0109 return d->configStartServerOnStartupEntry; 0110 } 0111 0112 void DMediaServerMngr::cleanUp() 0113 { 0114 delete d->server; 0115 d->server = nullptr; 0116 } 0117 0118 bool DMediaServerMngr::loadAtStartup() 0119 { 0120 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0121 KConfigGroup dlnaConfigGroup = config->group(configGroupName()); 0122 bool startServerOnStartup = dlnaConfigGroup.readEntry(configStartServerOnStartupEntry(), false); 0123 bool result = true; 0124 0125 if (startServerOnStartup) 0126 { 0127 // Restore the old sharing configuration and start the server. 0128 0129 result &= load(); 0130 result &= startMediaServer(); 0131 0132 mediaServerNotification(result); 0133 0134 return result; 0135 } 0136 0137 return false; 0138 } 0139 0140 void DMediaServerMngr::saveAtShutdown() 0141 { 0142 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0143 KConfigGroup dlnaConfigGroup = config->group(configGroupName()); 0144 bool startServerOnStartup = dlnaConfigGroup.readEntry(configStartServerOnStartupEntry(), false); 0145 0146 if (startServerOnStartup) 0147 { 0148 // Save the current sharing configuration for the next session. 0149 0150 save(); 0151 } 0152 0153 cleanUp(); 0154 } 0155 0156 void DMediaServerMngr::mediaServerNotification(bool started) 0157 { 0158 DNotificationWrapper(QLatin1String("mediaserverloadstartup"), 0159 started ? i18n("Media Server have been started") 0160 : i18n("Media Server cannot be started!"), 0161 qApp->activeWindow(), qApp->applicationName()); 0162 } 0163 0164 void DMediaServerMngr::setItemsList(const QString& aname, const QList<QUrl>& urls) 0165 { 0166 d->collectionMap.clear(); 0167 d->collectionMap.insert(aname, urls); 0168 } 0169 0170 QList<QUrl> DMediaServerMngr::itemsList() const 0171 { 0172 QList<QUrl> ret; 0173 0174 if (!d->collectionMap.isEmpty()) 0175 { 0176 QList<QList<QUrl> > ulst = d->collectionMap.values(); 0177 0178 Q_FOREACH (const QList<QUrl>& urls, ulst) 0179 { 0180 ret << urls; 0181 } 0182 } 0183 0184 return ret; 0185 } 0186 0187 void DMediaServerMngr::setCollectionMap(const MediaServerMap& map) 0188 { 0189 d->collectionMap = map; 0190 } 0191 0192 MediaServerMap DMediaServerMngr::collectionMap() const 0193 { 0194 return d->collectionMap; 0195 } 0196 0197 bool DMediaServerMngr::startMediaServer() 0198 { 0199 if (!d->server) 0200 { 0201 d->server = new DMediaServer(); 0202 0203 if (!d->server->init()) 0204 { 0205 cleanUp(); 0206 0207 return false; 0208 } 0209 } 0210 0211 if (d->collectionMap.isEmpty()) 0212 { 0213 cleanUp(); 0214 0215 return false; 0216 } 0217 0218 d->server->addAlbumsOnServer(d->collectionMap); 0219 0220 return true; 0221 } 0222 0223 bool DMediaServerMngr::isRunning() const 0224 { 0225 return (d->server ? true : false); 0226 } 0227 0228 int DMediaServerMngr::albumsShared() const 0229 { 0230 if (d->collectionMap.isEmpty()) 0231 { 0232 return 0; 0233 } 0234 0235 return d->collectionMap.count(); 0236 } 0237 0238 int DMediaServerMngr::itemsShared() const 0239 { 0240 return itemsList().count(); 0241 } 0242 0243 bool DMediaServerMngr::save() 0244 { 0245 QDomDocument doc(QLatin1String("mediaserverlist")); 0246 doc.setContent(QString::fromUtf8("<!DOCTYPE XMLQueueList><mediaserverlist version=\"1.0\" client=\"digikam\" encoding=\"UTF-8\"/>")); 0247 QDomElement docElem = doc.documentElement(); 0248 0249 auto end = d->collectionMap.cend(); 0250 0251 for (auto it = d->collectionMap.cbegin() ; it != end ; ++it) 0252 { 0253 QDomElement elm = doc.createElement(QLatin1String("album")); 0254 elm.setAttribute(QLatin1String("title"), it.key()); 0255 0256 // ---------------------- 0257 0258 QDomElement data; 0259 0260 Q_FOREACH (const QUrl& url, it.value()) 0261 { 0262 data = doc.createElement(QLatin1String("path")); 0263 data.setAttribute(QLatin1String("value"), url.toLocalFile()); 0264 elm.appendChild(data); 0265 } 0266 0267 docElem.appendChild(elm); 0268 } 0269 0270 QFile file(d->mapsConf); 0271 0272 if (!file.open(QIODevice::WriteOnly)) 0273 { 0274 qCDebug(DIGIKAM_MEDIASRV_LOG) << "Cannot open XML file to store MediaServer list"; 0275 qCDebug(DIGIKAM_MEDIASRV_LOG) << file.fileName(); 0276 0277 return false; 0278 } 0279 0280 QTextStream stream(&file); 0281 #if QT_VERSION < QT_VERSION_CHECK(6,0,0) 0282 // In Qt5 only. Qt6 uses UTF-8 by default. 0283 stream.setCodec(QTextCodec::codecForName("UTF-8")); 0284 #endif 0285 stream.setAutoDetectUnicode(true); 0286 stream << doc.toString(4); 0287 file.close(); 0288 0289 return true; 0290 } 0291 0292 bool DMediaServerMngr::load() 0293 { 0294 QFile file(d->mapsConf); 0295 0296 if (file.exists()) 0297 { 0298 if (!file.open(QIODevice::ReadOnly)) 0299 { 0300 qCDebug(DIGIKAM_MEDIASRV_LOG) << "Cannot open XML file to load MediaServer list"; 0301 0302 return false; 0303 } 0304 0305 QDomDocument doc(QLatin1String("mediaserverlist")); 0306 0307 if (!doc.setContent(&file)) 0308 { 0309 qCDebug(DIGIKAM_MEDIASRV_LOG) << "Cannot load MediaServer list XML file"; 0310 file.close(); 0311 0312 return false; 0313 } 0314 0315 QDomElement docElem = doc.documentElement(); 0316 MediaServerMap map; 0317 QList<QUrl> urls; 0318 QString album; 0319 0320 for (QDomNode n = docElem.firstChild() ; !n.isNull() ; n = n.nextSibling()) 0321 { 0322 QDomElement e = n.toElement(); 0323 0324 if (e.isNull()) 0325 { 0326 continue; 0327 } 0328 0329 if (e.tagName() != QLatin1String("album")) 0330 { 0331 continue; 0332 } 0333 0334 album = e.attribute(QLatin1String("title")); 0335 urls.clear(); 0336 0337 for (QDomNode n2 = e.firstChild() ; !n2.isNull() ; n2 = n2.nextSibling()) 0338 { 0339 QDomElement e2 = n2.toElement(); 0340 0341 if (e2.isNull()) 0342 { 0343 continue; 0344 } 0345 0346 QString name2 = e2.tagName(); 0347 QString val2 = e2.attribute(QLatin1String("value")); 0348 0349 if (name2 == QLatin1String("path")) 0350 { 0351 urls << QUrl::fromLocalFile(val2); 0352 } 0353 } 0354 0355 map.insert(album, urls); 0356 } 0357 0358 setCollectionMap(map); 0359 file.close(); 0360 0361 return true; 0362 } 0363 else 0364 { 0365 return false; 0366 } 0367 } 0368 0369 } // namespace DigikamGenericMediaServerPlugin 0370 0371 #include "moc_dmediaservermngr.cpp"