Skip to content

Commit

Permalink
Initial work on creating .gp files
Browse files Browse the repository at this point in the history
Currently this creates the zip contents, with the version entry and an empty score.gpif xml file

Refactored the Gp7::Document header a bit so that the code for converting to XML can belong in a separate file.

#350
  • Loading branch information
cameronwhite committed Feb 8, 2022
1 parent 43315ae commit 19e645b
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 16 deletions.
5 changes: 3 additions & 2 deletions source/formats/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ set( srcs
gp7/converter.cpp
gp7/gp7exporter.cpp
gp7/gp7importer.cpp
gp7/parser.cpp
gp7/from_xml.cpp
gp7/to_xml.cpp

gpx/bitstream.cpp
gpx/filesystem.cpp
Expand Down Expand Up @@ -63,9 +64,9 @@ set( headers
fileformatmanager.h

gp7/converter.h
gp7/document.h
gp7/gp7exporter.h
gp7/gp7importer.h
gp7/parser.h

gpx/bitstream.h
gpx/filesystem.h
Expand Down
2 changes: 1 addition & 1 deletion source/formats/gp7/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

#include "converter.h"
#include "parser.h"
#include "document.h"

#include <boost/date_time/gregorian/gregorian_types.hpp>
#include <boost/rational.hpp>
Expand Down
10 changes: 6 additions & 4 deletions source/formats/gp7/parser.h → source/formats/gp7/document.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef FORMATS_GP7_PARSER_H
#define FORMATS_GP7_PARSER_H
#ifndef FORMATS_GP7_DOCUMENT_H
#define FORMATS_GP7_DOCUMENT_H

#include "score/timesignature.h"
#include <bitset>
#include <boost/rational.hpp>
#include <optional>
Expand Down Expand Up @@ -391,7 +390,10 @@ struct Document
};

/// Parses the score.gpif XML file.
Document parse(const pugi::xml_document &root, Version version);
Document from_xml(const pugi::xml_document &root, Version version);

/// Creates the score.gpif XML file from the intermediate representation.
pugi::xml_document to_xml(const Document &doc);

} // namespace Gp7

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "parser.h"
#include "document.h"

#include <formats/fileformat.h>
#include <score/generalmidi.h>
Expand Down Expand Up @@ -871,7 +871,7 @@ Gp7::Document::addRhythm(Beat &beat, Rhythm rhythm)
}

Gp7::Document
Gp7::parse(const pugi::xml_document &root, Version version)
Gp7::from_xml(const pugi::xml_document &root, Version version)
{
Gp7::Document doc;

Expand Down
113 changes: 112 additions & 1 deletion source/formats/gp7/gp7exporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,125 @@
#include "gp7exporter.h"

#include "gp7importer.h"
#include "document.h"

#include <memory>
#include <minizip/zip.h>
#ifdef _WIN32
#include <minizip/iowin32.h>
#endif

#include <pugixml.hpp>

Gp7Exporter::Gp7Exporter()
: FileFormatExporter(Gp7Importer::getFileFormat())
{
}

namespace
{
/// Custom deleter for use with std::unique_ptr.
struct ZipFileCloser
{
using pointer = zipFile;

void operator()(zipFile f)
{
if (f)
zipClose(f, nullptr);
}
};

/// Handle to a zipFile. Calls zipClose() when it goes out of scope.
using ZipFileHandle = std::unique_ptr<zipFile, ZipFileCloser>;

/// Opens a zip file for writing.
static ZipFileHandle
createZipFile(const std::filesystem::path &filename)
{
zlib_filefunc64_def ffunc;
#ifdef _WIN32
// Ensure wide strings are used, matching boost::filesystem::path.
fill_win32_filefunc64W(&ffunc);
#else
fill_fopen64_filefunc(&ffunc);
#endif

ZipFileHandle zip_file;
zip_file.reset(zipOpen2_64(filename.c_str(), 0, nullptr, &ffunc));
if (!zip_file)
throw FileFormatException("Failed to create zip file.");

return zip_file;
}

/// RAII wrapper for creating a file in the archive.
struct ZipFileEntry
{
ZipFileEntry(zipFile file, const char *filename) : myFile(file)
{
if (zipOpenNewFileInZip64(myFile, filename, nullptr, nullptr, 0,
nullptr, 0, nullptr, Z_DEFLATED,
Z_DEFAULT_COMPRESSION, 1) != ZIP_OK)
{
throw FileFormatException("Failed to create file entry.");
}
}

~ZipFileEntry()
{
[[maybe_unused]] const int ret = zipCloseFileInZip(myFile);
assert(ret == ZIP_OK);
}

zipFile myFile;
};

static void
writeVersionInfo(zipFile file)
{
ZipFileEntry entry(file, "VERSION");

const char *contents = "7.0";
zipWriteInFileInZip(file, contents, strlen(contents));
}

/// pugi::xml_writer implementation for writing chunks to a zip entry.
struct zip_entry_writer : public pugi::xml_writer
{
zip_entry_writer(zipFile file) : myFile(file)
{
}

void write(const void *data, size_t size) override
{
zipWriteInFileInZip(myFile, data, size);
}

zipFile myFile;
};

static void
writeScore(zipFile file, const Score &score)
{
ZipFileEntry entry(file, "Content/score.gpif");

// TODO - convert score to GP7
Gp7::Document doc;
pugi::xml_document xml_doc = Gp7::to_xml(doc);

zip_entry_writer writer(file);
xml_doc.save(writer);
}

} // namespace

void
Gp7Exporter::save(const std::filesystem::path &filename, const Score &score)
{
// TODO
// The .gp file format is just a zip file with a different extension.
ZipFileHandle zip_file = createZipFile(filename);

writeVersionInfo(zip_file.get());
writeScore(zip_file.get(), score);
}
4 changes: 2 additions & 2 deletions source/formats/gp7/gp7importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include "gp7importer.h"

#include "converter.h"
#include "parser.h"
#include "document.h"

#include <minizip/unzip.h>
#ifdef _WIN32
Expand Down Expand Up @@ -145,6 +145,6 @@ void Gp7Importer::load(const std::filesystem::path &filename, Score &score)
if (!result)
throw FileFormatException(result.description());

Gp7::Document doc = Gp7::parse(xml_doc, Gp7::Version::V7);
Gp7::Document doc = Gp7::from_xml(xml_doc, Gp7::Version::V7);
Gp7::convert(doc, score);
}
31 changes: 31 additions & 0 deletions source/formats/gp7/to_xml.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2022 Cameron White
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "document.h"

namespace Gp7
{
pugi::xml_document
to_xml(const Document &doc)
{
pugi::xml_document root;

// TODO

return root;
}
} // namespace Gp7
4 changes: 2 additions & 2 deletions source/formats/gpx/gpximporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

#include "filesystem.h"

#include <formats/gp7/parser.h>
#include <formats/gp7/document.h>
#include <formats/gp7/converter.h>
#include <score/score.h>

Expand Down Expand Up @@ -53,6 +53,6 @@ GpxImporter::load(const std::filesystem::path &filename, Score &score)
xml_doc.print(std::cerr);
#endif

Gp7::Document doc = Gp7::parse(xml_doc, Gp7::Version::V6);
Gp7::Document doc = Gp7::from_xml(xml_doc, Gp7::Version::V6);
Gp7::convert(doc, score);
}
2 changes: 1 addition & 1 deletion source/formats/guitar_pro/gp345to7converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#define FORMATS_GP_GP345TO7CONVERTER_H

#include "document.h"
#include <formats/gp7/parser.h>
#include <formats/gp7/document.h>

namespace Gp
{
Expand Down
2 changes: 1 addition & 1 deletion source/formats/guitar_pro/guitarproimporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include "gp345to7converter.h"

#include <formats/gp7/converter.h>
#include <formats/gp7/parser.h>
#include <formats/gp7/document.h>
#include <formats/guitar_pro/document.h>
#include <formats/guitar_pro/inputstream.h>
#include <fstream>
Expand Down

0 comments on commit 19e645b

Please sign in to comment.