annotate base/ResourceFinder.cpp @ 876:47aa3aeb687b tonioni

For outputs with unknown bin count or multiple bins with variable sample rate, create additional output models for bins beyond the first
author Chris Cannam
date Wed, 29 Jan 2014 09:31:22 +0000
parents e802e550a1f2
children 9a422d610058
rev   line source
Chris@679 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@679 2
Chris@679 3 /*
Chris@679 4 Sonic Visualiser
Chris@679 5 An audio file viewer and annotation editor.
Chris@679 6 Centre for Digital Music, Queen Mary, University of London.
Chris@679 7
Chris@679 8 This program is free software; you can redistribute it and/or
Chris@679 9 modify it under the terms of the GNU General Public License as
Chris@679 10 published by the Free Software Foundation; either version 2 of the
Chris@679 11 License, or (at your option) any later version. See the file
Chris@679 12 COPYING included with this distribution for more information.
Chris@679 13 */
Chris@679 14
Chris@679 15 /*
Chris@679 16 This is a modified version of a source file from the
Chris@679 17 Rosegarden MIDI and audio sequencer and notation editor.
Chris@679 18 This file copyright 2005-2011 Chris Cannam and the Rosegarden
Chris@679 19 development team.
Chris@679 20 */
Chris@679 21
Chris@679 22 #include "ResourceFinder.h"
Chris@679 23
Chris@679 24 #include <QDir>
Chris@679 25 #include <QFileInfo>
Chris@679 26 #include <QStringList>
Chris@679 27 #include <QProcess>
Chris@679 28 #include <QCoreApplication>
Chris@679 29
Chris@679 30 #include <cstdlib>
Chris@679 31 #include <iostream>
Chris@679 32
Chris@679 33 /**
Chris@679 34 Resource files may be found in three places:
Chris@679 35
Chris@679 36 * Bundled into the application as Qt4 resources. These may be
Chris@679 37 opened using Qt classes such as QFile, with "fake" file paths
Chris@679 38 starting with a colon. For example ":icons/fileopen.png".
Chris@679 39
Chris@679 40 * Installed with the package, or in the user's equivalent home
Chris@679 41 directory location. For example,
Chris@679 42
Chris@679 43 - on Linux, in /usr/share/<appname> or /usr/local/share/<appname>
Chris@679 44 - on Linux, in $HOME/.local/share/<appname>
Chris@679 45
Chris@679 46 - on OS/X, in /Library/Application Support/<appname>
Chris@679 47 - on OS/X, in $HOME/Library/Application Support/<appname>
Chris@679 48
Chris@679 49 - on Windows, in %ProgramFiles%/<company>/<appname>
Chris@680 50 - on Windows, in (where?) something from http://msdn.microsoft.com/en-us/library/dd378457%28v=vs.85%29.aspx ?
Chris@679 51
Chris@679 52 These locations are searched in reverse order (user-installed
Chris@679 53 copies take priority over system-installed copies take priority
Chris@679 54 over bundled copies). Also, /usr/local takes priority over /usr.
Chris@679 55 */
Chris@679 56
Chris@679 57 QStringList
Chris@679 58 ResourceFinder::getSystemResourcePrefixList()
Chris@679 59 {
Chris@679 60 // returned in order of priority
Chris@679 61
Chris@679 62 QStringList list;
Chris@679 63
Chris@679 64 #ifdef Q_OS_WIN32
Chris@679 65 char *programFiles = getenv("ProgramFiles");
Chris@679 66 if (programFiles && programFiles[0]) {
Chris@679 67 list << QString("%1/%2/%3")
Chris@679 68 .arg(programFiles)
Chris@679 69 .arg(qApp->organizationName())
Chris@679 70 .arg(qApp->applicationName());
Chris@679 71 } else {
Chris@679 72 list << QString("C:/Program Files/%1/%2")
Chris@679 73 .arg(qApp->organizationName())
Chris@679 74 .arg(qApp->applicationName());
Chris@679 75 }
Chris@679 76 #else
Chris@679 77 #ifdef Q_OS_MAC
Chris@733 78 list << QString("/Library/Application Support/%1")
Chris@679 79 .arg(qApp->applicationName());
Chris@679 80 #else
Chris@679 81 list << QString("/usr/local/share/%1")
Chris@679 82 .arg(qApp->applicationName());
Chris@679 83 list << QString("/usr/share/%1")
Chris@679 84 .arg(qApp->applicationName());
Chris@679 85 #endif
Chris@679 86 #endif
Chris@679 87
Chris@679 88 return list;
Chris@679 89 }
Chris@679 90
Chris@679 91 QString
Chris@679 92 ResourceFinder::getUserResourcePrefix()
Chris@679 93 {
Chris@680 94 #ifdef Q_OS_WIN32
Chris@680 95 char *homedrive = getenv("HOMEDRIVE");
Chris@680 96 char *homepath = getenv("HOMEPATH");
Chris@680 97 QString home;
Chris@680 98 if (homedrive && homepath) {
Chris@680 99 home = QString("%1%2").arg(homedrive).arg(homepath);
Chris@680 100 } else {
Chris@680 101 home = QDir::home().absolutePath();
Chris@680 102 }
Chris@680 103 if (home == "") return "";
Chris@708 104 return QString("%1/.%2").arg(home).arg(qApp->applicationName()); //!!! wrong
Chris@680 105 #else
Chris@679 106 char *home = getenv("HOME");
Chris@679 107 if (!home || !home[0]) return "";
Chris@679 108 #ifdef Q_OS_MAC
Chris@733 109 return QString("%1/Library/Application Support/%2")
Chris@679 110 .arg(home)
Chris@679 111 .arg(qApp->applicationName());
Chris@679 112 #else
Chris@679 113 return QString("%1/.local/share/%2")
Chris@679 114 .arg(home)
Chris@679 115 .arg(qApp->applicationName());
Chris@679 116 #endif
Chris@679 117 #endif
Chris@679 118 }
Chris@679 119
Chris@679 120 QStringList
Chris@679 121 ResourceFinder::getResourcePrefixList()
Chris@679 122 {
Chris@679 123 // returned in order of priority
Chris@679 124
Chris@679 125 QStringList list;
Chris@679 126
Chris@679 127 QString user = getUserResourcePrefix();
Chris@679 128 if (user != "") list << user;
Chris@679 129
Chris@679 130 list << getSystemResourcePrefixList();
Chris@679 131
Chris@679 132 list << ":"; // bundled resource location
Chris@679 133
Chris@679 134 return list;
Chris@679 135 }
Chris@679 136
Chris@679 137 QString
Chris@679 138 ResourceFinder::getResourcePath(QString resourceCat, QString fileName)
Chris@679 139 {
Chris@679 140 // We don't simply call getResourceDir here, because that returns
Chris@679 141 // only the "installed file" location. We also want to search the
Chris@679 142 // bundled resources and user-saved files.
Chris@679 143
Chris@679 144 QStringList prefixes = getResourcePrefixList();
Chris@679 145
Chris@679 146 if (resourceCat != "") resourceCat = "/" + resourceCat;
Chris@679 147
Chris@679 148 for (QStringList::const_iterator i = prefixes.begin();
Chris@679 149 i != prefixes.end(); ++i) {
Chris@679 150
Chris@679 151 QString prefix = *i;
Chris@679 152
Chris@690 153 SVDEBUG << "ResourceFinder::getResourcePath: Looking up file \"" << fileName << "\" for category \"" << resourceCat << "\" in prefix \"" << prefix << "\"" << endl;
Chris@679 154
Chris@679 155 QString path =
Chris@679 156 QString("%1%2/%3").arg(prefix).arg(resourceCat).arg(fileName);
Chris@679 157 if (QFileInfo(path).exists() && QFileInfo(path).isReadable()) {
Chris@843 158 cerr << "Found it!" << endl;
Chris@679 159 return path;
Chris@679 160 }
Chris@679 161 }
Chris@679 162
Chris@679 163 return "";
Chris@679 164 }
Chris@679 165
Chris@679 166 QString
Chris@679 167 ResourceFinder::getResourceDir(QString resourceCat)
Chris@679 168 {
Chris@679 169 // Returns only the "installed file" location
Chris@679 170
Chris@679 171 QStringList prefixes = getSystemResourcePrefixList();
Chris@679 172
Chris@679 173 if (resourceCat != "") resourceCat = "/" + resourceCat;
Chris@679 174
Chris@679 175 for (QStringList::const_iterator i = prefixes.begin();
Chris@679 176 i != prefixes.end(); ++i) {
Chris@679 177
Chris@679 178 QString prefix = *i;
Chris@679 179 QString path = QString("%1%2").arg(prefix).arg(resourceCat);
Chris@679 180 if (QFileInfo(path).exists() &&
Chris@679 181 QFileInfo(path).isDir() &&
Chris@679 182 QFileInfo(path).isReadable()) {
Chris@679 183 return path;
Chris@679 184 }
Chris@679 185 }
Chris@679 186
Chris@679 187 return "";
Chris@679 188 }
Chris@679 189
Chris@679 190 QString
Chris@679 191 ResourceFinder::getResourceSavePath(QString resourceCat, QString fileName)
Chris@679 192 {
Chris@679 193 QString dir = getResourceSaveDir(resourceCat);
Chris@679 194 if (dir == "") return "";
Chris@679 195
Chris@679 196 return dir + "/" + fileName;
Chris@679 197 }
Chris@679 198
Chris@679 199 QString
Chris@679 200 ResourceFinder::getResourceSaveDir(QString resourceCat)
Chris@679 201 {
Chris@679 202 // Returns the "user" location
Chris@679 203
Chris@679 204 QString user = getUserResourcePrefix();
Chris@679 205 if (user == "") return "";
Chris@679 206
Chris@679 207 if (resourceCat != "") resourceCat = "/" + resourceCat;
Chris@679 208
Chris@679 209 QDir userDir(user);
Chris@679 210 if (!userDir.exists()) {
Chris@679 211 if (!userDir.mkpath(user)) {
Chris@843 212 cerr << "ResourceFinder::getResourceSaveDir: ERROR: Failed to create user resource path \"" << user << "\"" << endl;
Chris@679 213 return "";
Chris@679 214 }
Chris@679 215 }
Chris@679 216
Chris@679 217 if (resourceCat != "") {
Chris@679 218 QString save = QString("%1%2").arg(user).arg(resourceCat);
Chris@679 219 QDir saveDir(save);
Chris@679 220 if (!saveDir.exists()) {
Chris@679 221 if (!userDir.mkpath(save)) {
Chris@843 222 cerr << "ResourceFinder::getResourceSaveDir: ERROR: Failed to create user resource path \"" << save << "\"" << endl;
Chris@679 223 return "";
Chris@679 224 }
Chris@679 225 }
Chris@679 226 return save;
Chris@679 227 } else {
Chris@679 228 return user;
Chris@679 229 }
Chris@679 230 }
Chris@679 231
Chris@679 232 QStringList
Chris@679 233 ResourceFinder::getResourceFiles(QString resourceCat, QString fileExt)
Chris@679 234 {
Chris@679 235 QStringList results;
Chris@679 236 QStringList prefixes = getResourcePrefixList();
Chris@679 237
Chris@679 238 QStringList filters;
Chris@679 239 filters << QString("*.%1").arg(fileExt);
Chris@679 240
Chris@679 241 for (QStringList::const_iterator i = prefixes.begin();
Chris@679 242 i != prefixes.end(); ++i) {
Chris@679 243
Chris@679 244 QString prefix = *i;
Chris@679 245 QString path;
Chris@679 246
Chris@679 247 if (resourceCat != "") {
Chris@679 248 path = QString("%1/%2").arg(prefix).arg(resourceCat);
Chris@679 249 } else {
Chris@679 250 path = prefix;
Chris@679 251 }
Chris@679 252
Chris@679 253 QDir dir(path);
Chris@679 254 if (!dir.exists()) continue;
Chris@679 255
Chris@679 256 dir.setNameFilters(filters);
Chris@679 257 QStringList entries = dir.entryList
Chris@679 258 (QDir::Files | QDir::Readable, QDir::Name);
Chris@679 259
Chris@679 260 for (QStringList::const_iterator j = entries.begin();
Chris@679 261 j != entries.end(); ++j) {
Chris@679 262 results << QString("%1/%2").arg(path).arg(*j);
Chris@679 263 }
Chris@679 264 }
Chris@679 265
Chris@679 266 return results;
Chris@679 267 }
Chris@679 268
Chris@679 269 bool
Chris@679 270 ResourceFinder::unbundleResource(QString resourceCat, QString fileName)
Chris@679 271 {
Chris@679 272 QString path = getResourcePath(resourceCat, fileName);
Chris@679 273
Chris@679 274 if (!path.startsWith(':')) return true;
Chris@679 275
Chris@679 276 // This is the lowest-priority alternative path for this
Chris@679 277 // resource, so we know that there must be no installed copy.
Chris@679 278 // Install one to the user location.
Chris@690 279 SVDEBUG << "ResourceFinder::unbundleResource: File " << fileName << " is bundled, un-bundling it" << endl;
Chris@679 280 QString target = getResourceSavePath(resourceCat, fileName);
Chris@679 281 QFile file(path);
Chris@679 282 if (!file.copy(target)) {
Chris@843 283 cerr << "ResourceFinder::unbundleResource: ERROR: Failed to un-bundle resource file \"" << fileName << "\" to user location \"" << target << "\"" << endl;
Chris@679 284 return false;
Chris@679 285 }
Chris@679 286
Chris@679 287 QFile chmod(target);
Chris@679 288 chmod.setPermissions(QFile::ReadOwner |
Chris@679 289 QFile::ReadUser | /* for potential platform-independence */
Chris@679 290 QFile::ReadGroup |
Chris@679 291 QFile::ReadOther |
Chris@679 292 QFile::WriteOwner|
Chris@679 293 QFile::WriteUser); /* for potential platform-independence */
Chris@679 294
Chris@679 295 return true;
Chris@679 296 }
Chris@679 297