2013-04-05 04:53:59 +02:00
|
|
|
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
|
2006-01-16 22:02:54 +01:00
|
|
|
//
|
2011-09-28 21:44:07 +02:00
|
|
|
// Permission to use, copy, modify, and distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice appear in all copies.
|
2006-01-16 22:02:54 +01:00
|
|
|
//
|
2011-09-28 21:44:07 +02:00
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
2006-01-16 22:02:54 +01:00
|
|
|
//
|
2009-07-29 07:43:02 +02:00
|
|
|
// Aegisub Project http://www.aegisub.org/
|
|
|
|
|
2013-04-05 04:53:59 +02:00
|
|
|
#include <libaegisub/signal.h>
|
|
|
|
|
2013-06-10 15:58:13 +02:00
|
|
|
#include <memory>
|
2011-09-28 21:44:07 +02:00
|
|
|
#include <set>
|
2013-04-05 04:53:59 +02:00
|
|
|
#include <unordered_map>
|
2009-09-11 04:36:34 +02:00
|
|
|
#include <vector>
|
2011-09-29 20:17:37 +02:00
|
|
|
#include <wx/bitmap.h>
|
2012-10-06 18:39:44 +02:00
|
|
|
#include <wx/timer.h>
|
2009-09-11 04:36:34 +02:00
|
|
|
#include <wx/window.h>
|
|
|
|
|
2006-01-16 22:02:54 +01:00
|
|
|
class AssDialogue;
|
2011-09-28 21:44:07 +02:00
|
|
|
class AssKaraoke;
|
|
|
|
class wxButton;
|
2014-07-09 16:22:49 +02:00
|
|
|
namespace agi { class AudioProvider; }
|
2011-09-28 21:44:07 +02:00
|
|
|
namespace agi { struct Context; }
|
2006-01-27 01:48:59 +01:00
|
|
|
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
/// @class AudioKaraoke
|
2011-09-28 21:44:07 +02:00
|
|
|
/// @brief Syllable split and join UI for karaoke
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
///
|
2011-09-28 21:44:07 +02:00
|
|
|
/// This class has two main responsibilities: the syllable split/join UI, and
|
|
|
|
/// the karaoke mode controller. The split/join UI consists of the dialogue
|
|
|
|
/// line with spaces and lines at each syllable split point. Clicking on a line
|
|
|
|
/// removes that \k tag; clicking anywhere else inserts a new \k tag with
|
|
|
|
/// interpolated duration. Added or removed splits are not autocommitted and
|
|
|
|
/// must be explicitly accepted or rejected. This is for two reasons:
|
|
|
|
/// 1. It's easy for a stray click on the split/join bar to go unnoticed,
|
|
|
|
/// making autocommitting somewhat error-prone.
|
|
|
|
/// 2. When a line with zero \k tags is activated, it's automatically split
|
|
|
|
/// at each space. This clearly should not automatically update the line
|
|
|
|
/// (changing the active selection should never directly change the file
|
|
|
|
/// itself), so there must be a notion of pending splits.
|
|
|
|
///
|
|
|
|
/// As the karaoke controller, it owns the AssKaraoke instance shared by this
|
|
|
|
/// class and the karaoke timing controller, and is responsible for switching
|
|
|
|
/// between timing controllers when entering and leaving karaoke mode. Ideally
|
|
|
|
/// the creation of the dialogue timing controller should probably be done
|
|
|
|
/// elsewhere, but there currently isn't any particularly appropriate place and
|
|
|
|
/// it's not worth caring about. The KaraokeController duties should perhaps be
|
|
|
|
/// split off into its own class, but at the moment they're insignificant
|
|
|
|
/// enough that it's not worth it.
|
|
|
|
///
|
|
|
|
/// The shared AssKaraoke instance is primarily to improve the handling of
|
|
|
|
/// pending splits. When a split is added removed, or a line is autosplit,
|
|
|
|
/// the audio display immediately reflects the changes, but the file is not
|
|
|
|
/// actually updated until the line is committed (which if auto-commit timing
|
|
|
|
/// changes is on, will happen as soon as the user adjusts the timing of the
|
|
|
|
/// new syllable).
|
2014-03-13 02:39:07 +01:00
|
|
|
class AudioKaraoke final : public wxWindow {
|
2011-09-28 21:44:07 +02:00
|
|
|
agi::Context *c; ///< Project context
|
|
|
|
agi::signal::Connection file_changed; ///< File changed slot
|
2011-11-18 23:58:22 +01:00
|
|
|
agi::signal::Connection audio_opened; ///< Audio opened connection
|
|
|
|
agi::signal::Connection audio_closed; ///< Audio closed connection
|
2012-10-05 05:22:54 +02:00
|
|
|
agi::signal::Connection active_line_changed;
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Currently active dialogue line
|
2013-12-12 01:29:48 +01:00
|
|
|
AssDialogue *active_line = nullptr;
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Karaoke data
|
2013-06-10 15:58:13 +02:00
|
|
|
std::unique_ptr<AssKaraoke> kara;
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Current line's stripped text with spaces added between each syllable
|
2013-04-05 04:53:59 +02:00
|
|
|
std::vector<wxString> spaced_text;
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-09-29 20:17:37 +02:00
|
|
|
/// spaced_text + syl_lines rendered to a bitmap
|
|
|
|
wxBitmap rendered_line;
|
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Indexes in spaced_text which are the beginning of syllables
|
|
|
|
std::vector<int> syl_start_points;
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
/// x coordinate in pixels of the separator lines of each syllable
|
|
|
|
std::vector<int> syl_lines;
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Left x coordinate of each character in spaced_text in pixels
|
|
|
|
std::vector<int> char_x;
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2013-04-05 04:53:59 +02:00
|
|
|
/// Mapping from character index to byte position in the relevant syllable's text
|
|
|
|
std::vector<size_t> char_to_byte;
|
|
|
|
|
|
|
|
/// Cached width of characters from GetTextExtent
|
|
|
|
std::unordered_map<std::string, int> char_widths;
|
|
|
|
|
2013-12-12 01:29:48 +01:00
|
|
|
int scroll_x = 0; ///< Distance the display has been shifted to the left in pixels
|
|
|
|
int scroll_dir = 0; ///< Direction the display will be scrolled on scroll_timer ticks (+/- 1)
|
2012-10-05 17:04:46 +02:00
|
|
|
wxTimer scroll_timer; ///< Timer to scroll every 50ms when user holds down scroll button
|
2012-10-01 19:25:48 +02:00
|
|
|
|
2013-12-12 01:29:48 +01:00
|
|
|
int char_height = 0; ///< Maximum character height in pixels
|
|
|
|
int char_width = 0; ///< Maximum character width in pixels
|
|
|
|
int mouse_pos = 0; ///< Last x coordinate of the mouse
|
|
|
|
bool click_will_remove_split = false; ///< If true a click at mouse_pos will remove a split rather than adding one
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
wxFont split_font; ///< Font used in the split/join interface
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2013-12-12 01:29:48 +01:00
|
|
|
bool enabled = false; ///< Is karaoke mode enabled?
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
wxButton *accept_button; ///< Accept pending splits button
|
|
|
|
wxButton *cancel_button; ///< Revert pending changes
|
2006-02-23 22:56:46 +01:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
wxWindow *split_area; ///< The split/join window
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Load syllable data from the currently active line
|
|
|
|
void LoadFromLine();
|
|
|
|
/// Cache presentational data from the loaded syllable data
|
|
|
|
void SetDisplayText();
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Helper function for context menu creation
|
2012-12-30 00:53:56 +01:00
|
|
|
void AddMenuItem(wxMenu &menu, std::string const& tag, wxString const& help, std::string const& selected);
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Set the karaoke tags for the selected syllables to the indicated one
|
2012-12-30 00:53:56 +01:00
|
|
|
void SetTagType(std::string const& new_type);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-09-29 20:17:37 +02:00
|
|
|
/// Prerender the current line along with syllable split lines
|
|
|
|
void RenderText();
|
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Refresh the area of the display around a single character
|
|
|
|
/// @param pos Index in spaced_text
|
|
|
|
void LimitedRefresh(int pos);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Reset all pending split information and return to normal mode
|
|
|
|
void CancelSplit();
|
|
|
|
/// Apply any pending split information to the syllable data and return to normal mode
|
|
|
|
void AcceptSplit();
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
void OnActiveLineChanged(AssDialogue *new_line);
|
|
|
|
void OnContextMenu(wxContextMenuEvent&);
|
|
|
|
void OnEnableButton(wxCommandEvent &evt);
|
2014-03-07 19:58:51 +01:00
|
|
|
void OnFileChanged(int type, std::set<const AssDialogue *> const& changed);
|
2011-09-28 21:44:07 +02:00
|
|
|
void OnMouse(wxMouseEvent &event);
|
|
|
|
void OnPaint(wxPaintEvent &event);
|
2012-10-02 00:21:18 +02:00
|
|
|
void OnSize(wxSizeEvent &event);
|
2014-07-09 16:22:49 +02:00
|
|
|
void OnAudioOpened(agi::AudioProvider *provider);
|
2012-10-01 19:25:48 +02:00
|
|
|
void OnScrollTimer(wxTimerEvent &event);
|
2006-06-27 06:04:40 +02:00
|
|
|
|
|
|
|
public:
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Constructor
|
|
|
|
/// @param parent Parent window
|
|
|
|
/// @param c Project context
|
|
|
|
AudioKaraoke(wxWindow *parent, agi::Context *c);
|
|
|
|
/// Destructor
|
|
|
|
~AudioKaraoke();
|
|
|
|
|
|
|
|
/// Is karaoke mode currently enabled?
|
|
|
|
bool IsEnabled() const { return enabled; }
|
|
|
|
|
|
|
|
/// Enable or disable karaoke mode
|
|
|
|
void SetEnabled(bool enable);
|
2006-06-27 06:04:40 +02:00
|
|
|
};
|