2006-01-16 22:02:54 +01:00
|
|
|
// Copyright (c) 2005, Rodrigo Braz Monteiro
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are met:
|
|
|
|
//
|
|
|
|
// * Redistributions of source code must retain the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer.
|
|
|
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
|
|
// and/or other materials provided with the distribution.
|
|
|
|
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
|
|
// may be used to endorse or promote products derived from this software
|
|
|
|
// without specific prior written permission.
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
//
|
2009-07-29 07:43:02 +02:00
|
|
|
// Aegisub Project http://www.aegisub.org/
|
|
|
|
|
2013-01-26 02:57:46 +01:00
|
|
|
#include "ass_entry.h"
|
2009-09-11 04:36:34 +02:00
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
#include <libaegisub/fs_fwd.h>
|
2010-12-31 22:02:42 +01:00
|
|
|
#include <libaegisub/signal.h>
|
2010-12-07 20:09:28 +01:00
|
|
|
|
2013-01-26 02:57:46 +01:00
|
|
|
#include <boost/intrusive/list.hpp>
|
|
|
|
#include <set>
|
|
|
|
#include <vector>
|
2012-10-12 19:16:39 +02:00
|
|
|
|
2014-03-07 19:58:51 +01:00
|
|
|
class AssAttachment;
|
2006-01-16 22:02:54 +01:00
|
|
|
class AssDialogue;
|
2014-03-07 19:58:51 +01:00
|
|
|
class AssInfo;
|
2006-01-16 22:02:54 +01:00
|
|
|
class AssStyle;
|
2013-01-26 02:57:46 +01:00
|
|
|
class wxString;
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2014-03-07 19:58:51 +01:00
|
|
|
template<typename T>
|
2014-03-08 01:59:52 +01:00
|
|
|
using EntryList = typename boost::intrusive::make_list<T, boost::intrusive::constant_time_size<false>, boost::intrusive::base_hook<AssEntryListHook>>::type;
|
2014-03-07 19:58:51 +01:00
|
|
|
|
2014-04-22 19:21:00 +02:00
|
|
|
using AegisubExtradataMap = std::map<uint32_t, std::pair<std::string, std::string>>;
|
|
|
|
|
2013-01-26 02:57:46 +01:00
|
|
|
struct AssFileCommit {
|
|
|
|
wxString const& message;
|
|
|
|
int *commit_id;
|
2014-03-07 19:58:51 +01:00
|
|
|
AssDialogue *single_line;
|
2013-01-26 02:57:46 +01:00
|
|
|
};
|
|
|
|
|
2014-05-22 03:32:42 +02:00
|
|
|
struct ProjectProperties {
|
|
|
|
std::string automation_scripts;
|
|
|
|
std::string export_filters;
|
|
|
|
std::string export_encoding;
|
|
|
|
std::string style_storage;
|
|
|
|
std::string audio_file;
|
|
|
|
std::string video_file;
|
|
|
|
std::string timecodes_file;
|
|
|
|
std::string keyframes_file;
|
|
|
|
std::map<std::string, std::string> automation_settings;
|
|
|
|
|
|
|
|
// UI State
|
|
|
|
double video_zoom = 0.;
|
|
|
|
double ar_value = 0.;
|
|
|
|
int scroll_position = 0;
|
|
|
|
int active_row = 0;
|
|
|
|
int ar_mode = 0;
|
|
|
|
int video_position = 0;
|
|
|
|
};
|
|
|
|
|
2006-01-16 22:02:54 +01:00
|
|
|
class AssFile {
|
2013-01-26 02:57:46 +01:00
|
|
|
/// A set of changes has been committed to the file (AssFile::COMMITType)
|
2014-03-07 19:58:51 +01:00
|
|
|
agi::signal::Signal<int, std::set<const AssDialogue*> const&> AnnounceCommit;
|
2013-01-26 02:57:46 +01:00
|
|
|
agi::signal::Signal<AssFileCommit> PushState;
|
2006-01-16 22:02:54 +01:00
|
|
|
public:
|
2010-06-16 08:20:14 +02:00
|
|
|
/// The lines in the file
|
2014-03-08 01:16:38 +01:00
|
|
|
std::vector<AssInfo> Info;
|
2014-03-07 19:58:51 +01:00
|
|
|
EntryList<AssStyle> Styles;
|
|
|
|
EntryList<AssDialogue> Events;
|
2014-03-08 02:13:23 +01:00
|
|
|
std::vector<AssAttachment> Attachments;
|
2014-04-22 19:21:00 +02:00
|
|
|
AegisubExtradataMap Extradata;
|
2014-05-22 03:32:42 +02:00
|
|
|
ProjectProperties Properties;
|
2014-04-22 19:21:00 +02:00
|
|
|
|
|
|
|
uint32_t next_extradata_id = 0;
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2014-03-07 19:58:51 +01:00
|
|
|
AssFile();
|
2010-06-22 02:03:33 +02:00
|
|
|
AssFile(const AssFile &from);
|
|
|
|
AssFile& operator=(AssFile from);
|
2006-01-16 22:02:54 +01:00
|
|
|
~AssFile();
|
|
|
|
|
2014-04-04 17:11:09 +02:00
|
|
|
EntryList<AssDialogue>::iterator iterator_to(AssDialogue& line);
|
|
|
|
|
2010-06-16 08:20:14 +02:00
|
|
|
/// @brief Load default file
|
|
|
|
/// @param defline Add a blank line to the file
|
2014-05-04 13:04:48 +02:00
|
|
|
/// @param style_catalog Style catalog name to fill styles from, blank to use default style
|
|
|
|
void LoadDefault(bool defline = true, std::string const& style_catalog = std::string());
|
2010-06-16 08:20:14 +02:00
|
|
|
/// Attach a file to the ass file
|
2013-01-04 16:01:50 +01:00
|
|
|
void InsertAttachment(agi::fs::path const& filename);
|
2010-06-16 08:20:14 +02:00
|
|
|
/// Get the names of all of the styles available
|
2012-12-30 01:32:36 +01:00
|
|
|
std::vector<std::string> GetStyles() const;
|
2010-06-16 08:20:14 +02:00
|
|
|
/// @brief Get a style by name
|
|
|
|
/// @param name Style name
|
2012-11-13 17:51:01 +01:00
|
|
|
/// @return Pointer to style or nullptr
|
2012-12-30 01:32:36 +01:00
|
|
|
AssStyle *GetStyle(std::string const& name);
|
2010-06-16 08:20:14 +02:00
|
|
|
|
2010-07-09 09:31:34 +02:00
|
|
|
void swap(AssFile &) throw();
|
2010-06-16 08:20:14 +02:00
|
|
|
|
|
|
|
/// @brief Get the script resolution
|
|
|
|
/// @param[out] w Width
|
|
|
|
/// @param[in] h Height
|
2012-03-20 01:39:10 +01:00
|
|
|
void GetResolution(int &w,int &h) const;
|
2012-01-25 20:07:36 +01:00
|
|
|
/// Get the value in a [Script Info] key as int, or 0 if it is not present
|
2013-01-04 16:01:50 +01:00
|
|
|
int GetScriptInfoAsInt(std::string const& key) const;
|
2010-06-16 08:20:14 +02:00
|
|
|
/// Get the value in a [Script Info] key as string.
|
2013-01-04 16:01:50 +01:00
|
|
|
std::string GetScriptInfo(std::string const& key) const;
|
2010-06-16 08:20:14 +02:00
|
|
|
/// Set the value of a [Script Info] key. Adds it if it doesn't exist.
|
2013-01-04 16:01:50 +01:00
|
|
|
void SetScriptInfo(std::string const& key, std::string const& value);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2014-04-22 19:21:00 +02:00
|
|
|
/// @brief Add a new extradata entry
|
|
|
|
/// @param key Class identifier/owner for the extradata
|
|
|
|
/// @param value Data for the extradata
|
|
|
|
/// @return ID of the created entry
|
|
|
|
uint32_t AddExtradata(std::string const& key, std::string const& value);
|
|
|
|
/// Fetch all extradata entries from a list of IDs
|
|
|
|
std::map<std::string, std::string> GetExtradata(std::vector<uint32_t> const& id_list) const;
|
|
|
|
/// Remove unreferenced extradata entries
|
|
|
|
void CleanExtradata();
|
|
|
|
|
2010-12-07 20:09:28 +01:00
|
|
|
/// Type of changes made in a commit
|
|
|
|
enum CommitType {
|
|
|
|
/// Potentially the entire file has been changed; any saved information
|
2011-09-15 07:16:32 +02:00
|
|
|
/// should be discarded. Note that the active line and selected set
|
|
|
|
/// should not be touched in handlers for this, as they may not have
|
|
|
|
/// been updated yet
|
|
|
|
/// Note that it is intentional that this cannot be combined with
|
|
|
|
/// other commit types
|
|
|
|
COMMIT_NEW = 0,
|
|
|
|
/// The order of lines in the file has changed
|
|
|
|
COMMIT_ORDER = 0x1,
|
|
|
|
/// The script info section has changed in some way
|
|
|
|
COMMIT_SCRIPTINFO = 0x2,
|
|
|
|
/// The styles have changed in some way
|
|
|
|
COMMIT_STYLES = 0x4,
|
|
|
|
/// The attachments have changed in some way
|
|
|
|
COMMIT_ATTACHMENT = 0x8,
|
|
|
|
/// Dialogue lines have been added or removed
|
|
|
|
/// Note that if the active dialogue line was removed, the active line
|
|
|
|
/// should be updated BEFORE committing
|
|
|
|
COMMIT_DIAG_ADDREM = 0x10,
|
|
|
|
/// The metadata fields of existing dialogue lines have changed
|
|
|
|
COMMIT_DIAG_META = 0x20,
|
|
|
|
/// The start and/or end times of existing dialogue lines have changed
|
|
|
|
COMMIT_DIAG_TIME = 0x40,
|
|
|
|
/// The text of existing dialogue lines have changed
|
|
|
|
COMMIT_DIAG_TEXT = 0x80,
|
2014-04-22 19:21:00 +02:00
|
|
|
COMMIT_DIAG_FULL = COMMIT_DIAG_META | COMMIT_DIAG_TIME | COMMIT_DIAG_TEXT,
|
|
|
|
/// Extradata entries were added/modified/removed
|
|
|
|
COMMIT_EXTRADATA = 0x100,
|
2010-12-07 20:09:28 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
DEFINE_SIGNAL_ADDERS(AnnounceCommit, AddCommitListener)
|
2013-01-26 02:57:46 +01:00
|
|
|
DEFINE_SIGNAL_ADDERS(PushState, AddUndoManager)
|
2010-12-07 20:09:28 +01:00
|
|
|
|
2010-07-09 09:31:34 +02:00
|
|
|
/// @brief Flag the file as modified and push a copy onto the undo stack
|
2011-09-28 21:44:24 +02:00
|
|
|
/// @param desc Undo description
|
|
|
|
/// @param type Type of changes made to the file in this commit
|
|
|
|
/// @param commitId Commit to amend rather than pushing a new commit
|
|
|
|
/// @param single_line Line which was changed, if only one line was
|
2010-07-09 09:31:34 +02:00
|
|
|
/// @return Unique identifier for the new undo group
|
2014-03-07 19:58:51 +01:00
|
|
|
int Commit(wxString const& desc, int type, int commitId = -1, AssDialogue *single_line = nullptr);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2010-05-19 02:44:44 +02:00
|
|
|
/// Comparison function for use when sorting
|
2014-03-07 19:58:51 +01:00
|
|
|
typedef bool (*CompFunc)(AssDialogue const& lft, AssDialogue const& rgt);
|
2010-05-19 02:44:44 +02:00
|
|
|
|
2012-01-31 01:44:34 +01:00
|
|
|
/// Compare based on start time
|
2014-03-07 19:58:51 +01:00
|
|
|
static bool CompStart(AssDialogue const& lft, AssDialogue const& rgt);
|
2012-01-31 01:44:34 +01:00
|
|
|
/// Compare based on end time
|
2014-03-07 19:58:51 +01:00
|
|
|
static bool CompEnd(AssDialogue const& lft, AssDialogue const& rgt);
|
2012-01-31 01:44:34 +01:00
|
|
|
/// Compare based on style name
|
2014-03-07 19:58:51 +01:00
|
|
|
static bool CompStyle(AssDialogue const& lft, AssDialogue const& rgt);
|
2012-01-31 01:44:34 +01:00
|
|
|
/// Compare based on actor name
|
2014-03-07 19:58:51 +01:00
|
|
|
static bool CompActor(AssDialogue const& lft, AssDialogue const& rgt);
|
2012-01-31 01:44:34 +01:00
|
|
|
/// Compare based on effect
|
2014-03-07 19:58:51 +01:00
|
|
|
static bool CompEffect(AssDialogue const& lft, AssDialogue const& rgt);
|
2012-07-23 02:44:44 +02:00
|
|
|
/// Compare based on layer
|
2014-03-07 19:58:51 +01:00
|
|
|
static bool CompLayer(AssDialogue const& lft, AssDialogue const& rgt);
|
2010-05-19 02:44:44 +02:00
|
|
|
|
|
|
|
/// @brief Sort the dialogue lines in this file
|
|
|
|
/// @param comp Comparison function to use. Defaults to sorting by start time.
|
2012-03-07 23:41:12 +01:00
|
|
|
/// @param limit If non-empty, only lines in this set are sorted
|
|
|
|
void Sort(CompFunc comp = CompStart, std::set<AssDialogue*> const& limit = std::set<AssDialogue*>());
|
2010-05-19 02:44:44 +02:00
|
|
|
/// @brief Sort the dialogue lines in the given list
|
|
|
|
/// @param comp Comparison function to use. Defaults to sorting by start time.
|
2012-03-07 23:41:12 +01:00
|
|
|
/// @param limit If non-empty, only lines in this set are sorted
|
2014-03-07 19:58:51 +01:00
|
|
|
static void Sort(EntryList<AssDialogue>& lst, CompFunc comp = CompStart, std::set<AssDialogue*> const& limit = std::set<AssDialogue*>());
|
2006-01-16 22:02:54 +01:00
|
|
|
};
|
2014-04-22 19:21:00 +02:00
|
|
|
|