Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
5bfad37
Adds a baseDir for the local path
IanCaio Oct 25, 2020
1e89441
Starts implementing the makeBundle functionality
IanCaio Oct 26, 2020
f34e966
Starts implementing logic to go through resources
IanCaio Oct 26, 2020
ff9af55
Adds logic to copy files and update the project
IanCaio Oct 26, 2020
f59cc9c
Makes the writeBundle method more organized
IanCaio Oct 26, 2020
14992ff
Adds a project bundle folder
IanCaio Oct 28, 2020
c174b3e
Handles local paths when a project isn't open
IanCaio Oct 28, 2020
b76e9f8
Sanitizes the bundle name
IanCaio Oct 29, 2020
3aac591
Moves away from projectbundle folder concept
IanCaio Oct 29, 2020
3e86cd6
Adds an option to save project as bundle
IanCaio Oct 29, 2020
218c211
Fix local: prefix saving bug
IanCaio Oct 29, 2020
6b1e5ac
Adds a warning message box
IanCaio Oct 29, 2020
1b13381
Removes unused header
IanCaio Oct 29, 2020
dbffea7
Removes Vestige plugins bundling
IanCaio Oct 31, 2020
2c15d4e
Extracts code from loadProject to another method
IanCaio Oct 31, 2020
598396b
Merge branch 'master' into feature/localPath
IanCaio Nov 9, 2020
93915b9
Merge branch 'master' into feature/localPath
IanCaio Feb 21, 2021
88278ea
Removes debug warnings
IanCaio Feb 21, 2021
14c1d3c
Fixes small bug with error logging
IanCaio Feb 21, 2021
941ad2a
Merge branch 'master' into feature/localPath
IanCaio Mar 18, 2021
465900d
Saves the bundle in a newly created folder
IanCaio Mar 18, 2021
4459d3c
Enhances the name conflict workaround
IanCaio Mar 18, 2021
e0a4c12
Starts addressing Johannes review
IanCaio Mar 25, 2021
43b3dfd
Adds makebundle action to bash completion file
IanCaio Mar 25, 2021
45b62e8
Improves safety check on project files
IanCaio Mar 26, 2021
b8bbea6
Addresses Spekular change request
IanCaio Mar 26, 2021
0ea10ff
Makes hasLocalPlugins method const
IanCaio Mar 26, 2021
8970cc4
Replaces literal uses of "local:"
IanCaio Mar 27, 2021
18c6239
Fix some comments on the header and cpp file
IanCaio Mar 27, 2021
e0eba3c
Changes variable on PathUtil to const
IanCaio Mar 27, 2021
d1d50b5
Leave doxygen comment on CPP file only
IanCaio Mar 28, 2021
9ef814f
Fix doxygen comment @param
IanCaio Mar 28, 2021
64b652d
Remove assert statements
IanCaio Mar 28, 2021
efef46a
Skips local paths when looking for shortest path
IanCaio Mar 28, 2021
5ffc99c
Address Spekular's review
IanCaio Mar 31, 2021
91509bd
Replaces "ok" with "error"
IanCaio Mar 31, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/DataFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#ifndef DATA_FILE_H
#define DATA_FILE_H

#include <map>
#include <QDomDocument>

#include "lmms_export.h"
Expand Down Expand Up @@ -72,6 +73,7 @@ class LMMS_EXPORT DataFile : public QDomDocument

void write( QTextStream& strm );
bool writeFile( const QString& fn );
bool writeBundle(const QString& fn);

QDomElement& content()
{
Expand Down Expand Up @@ -121,6 +123,9 @@ class LMMS_EXPORT DataFile : public QDomDocument
// List of ProjectVersions for the legacyFileVersion method
static const std::vector<ProjectVersion> UPGRADE_VERSIONS;

// Map with DOM elements that access resources (for making bundles)
static const std::map<QString, std::vector<QString>> ELEMENTS_WITH_RESOURCES;

void upgrade();

void loadData( const QByteArray & _data, const QString & _sourceFile );
Expand Down
3 changes: 2 additions & 1 deletion include/PathUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
namespace PathUtil
{
enum class Base { Absolute, ProjectDir, FactorySample, UserSample, UserVST, Preset,
UserLADSPA, DefaultLADSPA, UserSoundfont, DefaultSoundfont, UserGIG, DefaultGIG };
UserLADSPA, DefaultLADSPA, UserSoundfont, DefaultSoundfont, UserGIG, DefaultGIG,
LocalDir };

//! Return the directory associated with a given base as a QString
QString LMMS_EXPORT baseLocation(const Base base);
Expand Down
143 changes: 143 additions & 0 deletions src/core/DataFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@
#include "DataFile.h"

#include <math.h>
#include <map>

#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QMessageBox>

#include "base64.h"
Expand All @@ -43,12 +45,20 @@
#include "ProjectVersion.h"
#include "SongEditor.h"
#include "TextFloat.h"
#include "PathUtil.h"

#include "lmmsversion.h"

static void findIds(const QDomElement& elem, QList<jo_id_t>& idList);


// QMap with the DOM elements that access file resources
const std::map<QString, std::vector<QString>> DataFile::ELEMENTS_WITH_RESOURCES = {
{ "sampletco", {"src"} },
{ "audiofileprocessor", {"src"} },
{ "vestige", {"plugin"} }
};

// Vector with all the upgrade methods
const std::vector<DataFile::UpgradeMethod> DataFile::UPGRADE_METHODS = {
&DataFile::upgrade_0_2_1_20070501 , &DataFile::upgrade_0_2_1_20070508,
Expand Down Expand Up @@ -326,6 +336,139 @@ bool DataFile::writeFile( const QString& filename )



// TODO: Remove qWarnings
bool DataFile::writeBundle(const QString& filename)
{
qWarning() << "Write Bundle DEBUG:";

const QString fullName = nameWithExtension(filename);
const QString fullNameTemp = fullName + ".new";
const QString resourcesDirName = QFileInfo(fullName).path() + "/resources";

qWarning() << "Destination File: " << fullName;
qWarning() << "Resources Folder: " << resourcesDirName;

QFile outfile(fullNameTemp);

if (!outfile.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
if (gui)
{
QMessageBox::critical(NULL,
SongEditor::tr("Could not write file"),
SongEditor::tr("Could not open %1 for writing. You probably are not permitted to "
"write to this file. Please make sure you have write-access to "
"the file and try again.").arg(fullName));
}
qWarning() << "ERROR: Failed to create bundle file!";
return false;
}

// Creates resources folder
if (QDir(resourcesDirName).exists())
{
qWarning() << "Warning: Resources dir already exists. Proceeding anyways.";
}
else
{
if(!QDir().mkdir(resourcesDirName))
{
qWarning() << "ERROR: Failed to create resources dir!";
return false;
}
}

// Files will be named by the counter number + file extension
// to avoid name conflicts
unsigned int resCounter = 1;

std::map<QString,std::vector<QString>>::const_iterator it = ELEMENTS_WITH_RESOURCES.begin();

// Copy resources and manipulate the DataFile to have local paths to them
while(it != ELEMENTS_WITH_RESOURCES.end())
{
qWarning() << "Looking for resources on: " << it->first;
QDomNodeList list = elementsByTagName(it->first);

// Go through all elements with the tagname from our map
for (int i = 0; !list.item(i).isNull(); ++i)
{
QDomElement el = list.item(i).toElement();

std::vector<QString>::const_iterator res = it->second.begin();

// Search for attributes that point to resources
while(res != it->second.end())
{
qWarning() << "Attribute: " << *res;
// If the element has that attribute
if(el.hasAttribute(*res))
{
// Get absolute path to resource
QString resPath = PathUtil::toAbsolute(el.attribute(*res));
// The new file name is the counter number + the file extension
QString finalFileName = QString::number(resCounter) + "." + resPath.section('.',-1);
// Final path is our resources dir + the new file name
QString finalPath = resourcesDirName + "/" + finalFileName;

qWarning() << "Original Resource: " << resPath;
qWarning() << "Resource Destination: " << finalPath;

// Copy resource file to the resources folder
if(!QFile::copy(resPath, finalPath))
{
qWarning("ERROR: Failed to copy resource");
return false;
}

// Update attribute path to point to the bundle file
QString newAtt = "local:resources/" + finalFileName;
el.setAttribute(*res, newAtt);

qWarning() << "New Path: " << newAtt;
// Increases file counter
++resCounter;
}
++res;
}
}
++it;
}

// Writes the final DataFile
if (fullName.section('.', -1) == "mmpz")
{
QString xml;
QTextStream ts(&xml);
write(ts);
outfile.write(qCompress(xml.toUtf8()));
}
else
{
QTextStream ts(&outfile);
write(ts);
}

outfile.close();

// Make sure the file has been written correctly
if (QFileInfo(outfile.fileName()).size() > 0)
{
// Remove current file if there's one
QFile::remove(fullName);
// Move temporary file to current file
QFile::rename(fullNameTemp, fullName);

return true;
}

return false;
}





DataFile::Type DataFile::type( const QString& typeName )
{
for( int i = 0; i < TypeCount; ++i )
Expand Down
23 changes: 21 additions & 2 deletions src/core/PathUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
#include <QFileInfo>

#include "ConfigManager.h"
#include "Engine.h"
#include "Song.h"

namespace PathUtil
{
Base relativeBases[] = { Base::ProjectDir, Base::FactorySample, Base::UserSample, Base::UserVST, Base::Preset,
Base::UserLADSPA, Base::DefaultLADSPA, Base::UserSoundfont, Base::DefaultSoundfont, Base::UserGIG, Base::DefaultGIG };
Base::UserLADSPA, Base::DefaultLADSPA, Base::UserSoundfont, Base::DefaultSoundfont, Base::UserGIG, Base::DefaultGIG,
Base::LocalDir };

QString baseLocation(const Base base)
{
Expand All @@ -31,6 +34,21 @@ namespace PathUtil
case Base::DefaultSoundfont : loc = ConfigManager::inst()->userSf2Dir(); break;
case Base::UserGIG : loc = ConfigManager::inst()->gigDir(); break;
case Base::DefaultGIG : loc = ConfigManager::inst()->userGigDir(); break;
case Base::LocalDir :
{
Song* s = Engine::getSong();
if (s)
{
QString projectPath = s->projectFileName();
loc = QFileInfo(projectPath).path();
}
else
{
qWarning("PathUtil: No song loaded!");
return QString("");
}
break;
}
default : return QString("");
}
return QDir::cleanPath(loc) + "/";
Expand All @@ -57,7 +75,8 @@ namespace PathUtil
case Base::DefaultSoundfont : return QStringLiteral("defaultsoundfont:");
case Base::UserGIG : return QStringLiteral("usergig:");
case Base::DefaultGIG : return QStringLiteral("defaultgig:");
default : return QStringLiteral("");
case Base::LocalDir : return QStringLiteral("local:");
default : return QStringLiteral("");
}
}

Expand Down
22 changes: 22 additions & 0 deletions src/core/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,28 @@ int main( int argc, char * * argv )

return EXIT_SUCCESS;
}
else if (arg == "makeBundle" || arg == "--makeBundle")
{
++i;

if (i == argc)
{
return noInputFileError();
}

DataFile dataFile(QString::fromLocal8Bit(argv[i]));

if (argc > i+1) // Output file given
{
printf("Making bundle\n");
dataFile.writeBundle(QString::fromLocal8Bit(argv[i+1]));
return EXIT_SUCCESS;
}
else
{
return usageError("No output file specified.");
}
}
else if( arg == "--allowroot" )
{
// Ignore, processed earlier
Expand Down