forked from mia/Aegisub
Make video and audio providers throw typed exceptions.
Don't display error messages and try other providers when the user cancels loading a file. Remove files from the MRU lists if they can't be found. Closes #717. Originally committed to SVN as r4717.
This commit is contained in:
parent
71fb04cd29
commit
c10e9e3a5b
65 changed files with 574 additions and 1279 deletions
|
@ -131,16 +131,13 @@ namespace Endian {
|
||||||
|
|
||||||
|
|
||||||
#ifndef HAVE_DYNAMIC_ENDIAN
|
#ifndef HAVE_DYNAMIC_ENDIAN
|
||||||
|
|
||||||
|
|
||||||
// Regular, fast, templatized conditional reversing
|
// Regular, fast, templatized conditional reversing
|
||||||
|
|
||||||
template <class T>
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param val
|
/// @param val
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
template <class T>
|
||||||
inline T LittleToMachine(T val)
|
inline T LittleToMachine(T val)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_BIG_ENDIAN
|
#ifdef HAVE_BIG_ENDIAN
|
||||||
|
@ -152,12 +149,11 @@ namespace Endian {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param val
|
/// @param val
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
template <class T>
|
||||||
inline T BigToMachine(T val)
|
inline T BigToMachine(T val)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LITTLE_ENDIAN
|
#ifdef HAVE_LITTLE_ENDIAN
|
||||||
|
@ -169,12 +165,11 @@ namespace Endian {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param val
|
/// @param val
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
template <class T>
|
||||||
inline T MachineToLittle(T val)
|
inline T MachineToLittle(T val)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_BIG_ENDIAN
|
#ifdef HAVE_BIG_ENDIAN
|
||||||
|
@ -186,12 +181,11 @@ namespace Endian {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param val
|
/// @param val
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
template <class T>
|
||||||
inline T MachineToBig(T val)
|
inline T MachineToBig(T val)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LITTLE_ENDIAN
|
#ifdef HAVE_LITTLE_ENDIAN
|
||||||
|
@ -203,10 +197,8 @@ namespace Endian {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#else // HAVE_DYNAMIC_ENDIAN
|
#else // HAVE_DYNAMIC_ENDIAN
|
||||||
|
|
||||||
|
|
||||||
// Dynamic endianness handling
|
// Dynamic endianness handling
|
||||||
|
|
||||||
// Exploit that bit-shifting operations always can put bytes into
|
// Exploit that bit-shifting operations always can put bytes into
|
||||||
|
@ -216,13 +208,11 @@ namespace Endian {
|
||||||
// the endianness of the machine we are on, but it's the same
|
// the endianness of the machine we are on, but it's the same
|
||||||
// code for any platform!
|
// code for any platform!
|
||||||
|
|
||||||
|
|
||||||
// Unions to pack together ints and get their physical bytes
|
// Unions to pack together ints and get their physical bytes
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
union bytes16 {
|
union bytes16 {
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
uint8_t byte[2];
|
uint8_t byte[2];
|
||||||
|
|
||||||
|
@ -232,7 +222,6 @@ namespace Endian {
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
union bytes32 {
|
union bytes32 {
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
uint8_t byte[4];
|
uint8_t byte[4];
|
||||||
|
|
||||||
|
@ -242,7 +231,6 @@ namespace Endian {
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
union bytes64 {
|
union bytes64 {
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
uint8_t byte[8];
|
uint8_t byte[8];
|
||||||
|
|
||||||
|
@ -250,7 +238,6 @@ namespace Endian {
|
||||||
uint64_t word;
|
uint64_t word;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 16 bit words
|
// 16 bit words
|
||||||
|
|
||||||
|
|
||||||
|
@ -456,8 +443,5 @@ namespace Endian {
|
||||||
uint64_t(pack.byte[0]);
|
uint64_t(pack.byte[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,5 @@
|
||||||
// So unless we protect it by this, it gets included twice during production of precompiled
|
// So unless we protect it by this, it gets included twice during production of precompiled
|
||||||
// headers, which can cause problems with local includes.
|
// headers, which can cause problems with local includes.
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "agi_pre.h"
|
#include "agi_pre.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
#ifndef AGI_PRE_H
|
#ifndef AGI_PRE_H
|
||||||
|
|
||||||
/// @brief Inclusion guard.
|
/// @brief Inclusion guard.
|
||||||
/// @todo Why is this even nessicary? GCC seems to include agi_pre.h twice for no reason.
|
/// @todo Why is this even necessary? GCC seems to include agi_pre.h twice for no reason.
|
||||||
#define AGI_PRE_H
|
#define AGI_PRE_H
|
||||||
|
|
||||||
// C++ only
|
// C++ only
|
||||||
|
|
|
@ -34,12 +34,8 @@
|
||||||
/// @ingroup export
|
/// @ingroup export
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -48,21 +44,14 @@
|
||||||
#include <wx/window.h>
|
#include <wx/window.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//////////////
|
|
||||||
// Prototypes
|
|
||||||
class AssFile;
|
class AssFile;
|
||||||
class AssExportFilter;
|
class AssExportFilter;
|
||||||
class DialogExport;
|
class DialogExport;
|
||||||
class AssExporter;
|
class AssExporter;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
typedef std::list<AssExportFilter*> FilterList;
|
typedef std::list<AssExportFilter*> FilterList;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class AssExportFilterChain
|
/// @class AssExportFilterChain
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
|
@ -80,7 +69,6 @@ private:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
FilterList Unprepared;
|
FilterList Unprepared;
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
static std::auto_ptr<AssExportFilterChain> instance;
|
static std::auto_ptr<AssExportFilterChain> instance;
|
||||||
static FilterList *GetFilterList();
|
static FilterList *GetFilterList();
|
||||||
|
@ -90,8 +78,6 @@ public:
|
||||||
static void PrepareFilters();
|
static void PrepareFilters();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class AssExportFilter
|
/// @class AssExportFilter
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
|
@ -139,4 +125,3 @@ public:
|
||||||
virtual void LoadSettings(bool IsDefault); // Config dialog is done - extract data now.
|
virtual void LoadSettings(bool IsDefault); // Config dialog is done - extract data now.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,16 +36,11 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
|
||||||
#include <memory>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "ass_export_filter.h"
|
#include "ass_export_filter.h"
|
||||||
#include "ass_exporter.h"
|
#include "ass_exporter.h"
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "frame_main.h"
|
#include "frame_main.h"
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param subs
|
/// @param subs
|
||||||
///
|
///
|
||||||
|
@ -54,15 +49,11 @@ AssExporter::AssExporter (AssFile *subs) {
|
||||||
IsDefault = true;
|
IsDefault = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
///
|
///
|
||||||
AssExporter::~AssExporter () {
|
AssExporter::~AssExporter () {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Draw control settings
|
/// @brief Draw control settings
|
||||||
/// @param parent
|
/// @param parent
|
||||||
/// @param AddTo
|
/// @param AddTo
|
||||||
|
@ -90,8 +81,6 @@ void AssExporter::DrawSettings(wxWindow *parent,wxSizer *AddTo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Add filter to chain
|
/// @brief Add filter to chain
|
||||||
/// @param name
|
/// @param name
|
||||||
///
|
///
|
||||||
|
@ -113,8 +102,6 @@ void AssExporter::AddFilter(wxString name) {
|
||||||
Filters.push_back(filter);
|
Filters.push_back(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Adds all autoexporting filters to chain
|
/// @brief Adds all autoexporting filters to chain
|
||||||
///
|
///
|
||||||
void AssExporter::AddAutoFilters() {
|
void AssExporter::AddAutoFilters() {
|
||||||
|
@ -127,8 +114,6 @@ void AssExporter::AddAutoFilters() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get name of all filters
|
/// @brief Get name of all filters
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -142,8 +127,6 @@ wxArrayString AssExporter::GetAllFilterNames() {
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Transform for export
|
/// @brief Transform for export
|
||||||
/// @param export_dialog
|
/// @param export_dialog
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -162,8 +145,6 @@ AssFile *AssExporter::ExportTransform(wxWindow *export_dialog) {
|
||||||
return Subs;
|
return Subs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Export
|
/// @brief Export
|
||||||
/// @param filename
|
/// @param filename
|
||||||
/// @param charset
|
/// @param charset
|
||||||
|
@ -174,8 +155,6 @@ void AssExporter::Export(wxString filename, wxString charset, wxWindow *export_d
|
||||||
Subs->Save(filename,false,false,charset);
|
Subs->Save(filename,false,false,charset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get window associated with name
|
/// @brief Get window associated with name
|
||||||
/// @param name
|
/// @param name
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -186,8 +165,6 @@ wxSizer *AssExporter::GetSettingsSizer(wxString name) {
|
||||||
else return pos->second;
|
else return pos->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get description of filter
|
/// @brief Get description of filter
|
||||||
/// @param name
|
/// @param name
|
||||||
///
|
///
|
||||||
|
@ -201,5 +178,3 @@ wxString AssExporter::GetDescription(wxString name) {
|
||||||
}
|
}
|
||||||
throw wxString::Format(_T("Filter not found: %s"), name.c_str());
|
throw wxString::Format(_T("Filter not found: %s"), name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ namespace std {
|
||||||
/// @brief AssFile constructor
|
/// @brief AssFile constructor
|
||||||
AssFile::AssFile ()
|
AssFile::AssFile ()
|
||||||
: loaded(false)
|
: loaded(false)
|
||||||
|
, commitId(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,16 +110,17 @@ void AssFile::Load (const wxString &_filename,wxString charset,bool addToRecent)
|
||||||
|
|
||||||
// Read file
|
// Read file
|
||||||
if (reader) {
|
if (reader) {
|
||||||
reader->SetTarget(this);
|
AssFile temp;
|
||||||
|
reader->SetTarget(&temp);
|
||||||
reader->ReadFile(_filename,charset);
|
reader->ReadFile(_filename,charset);
|
||||||
|
swap(temp);
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Couldn't find a type
|
// Couldn't find a type
|
||||||
else throw _T("Unknown file type.");
|
else throw _T("Unknown file type.");
|
||||||
}
|
}
|
||||||
|
catch (agi::UserCancelException const&) { }
|
||||||
// String error
|
|
||||||
catch (const wchar_t *except) {
|
catch (const wchar_t *except) {
|
||||||
wxMessageBox(except,_T("Error loading file"),wxICON_ERROR | wxOK);
|
wxMessageBox(except,_T("Error loading file"),wxICON_ERROR | wxOK);
|
||||||
}
|
}
|
||||||
|
@ -154,7 +156,7 @@ void AssFile::Load (const wxString &_filename,wxString charset,bool addToRecent)
|
||||||
savedCommitId = commitId;
|
savedCommitId = commitId;
|
||||||
|
|
||||||
// Add to recent
|
// Add to recent
|
||||||
if (addToRecent) AddToRecent(_filename);
|
if (addToRecent && ok) AddToRecent(_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssFile::Save(wxString _filename,bool setfilename,bool addToRecent,const wxString encoding) {
|
void AssFile::Save(wxString _filename,bool setfilename,bool addToRecent,const wxString encoding) {
|
||||||
|
|
|
@ -920,6 +920,16 @@ void AudioDisplay::SetFile(wxString file) {
|
||||||
// Update
|
// Update
|
||||||
UpdateImage();
|
UpdateImage();
|
||||||
}
|
}
|
||||||
|
catch (agi::UserCancelException const&) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (agi::FileNotFoundError const& e) {
|
||||||
|
config::mru->Remove("Audio", STD_STR(file));
|
||||||
|
wxMessageBox(lagi_wxString(e.GetMessage()), L"Error loading audio",wxICON_ERROR | wxOK);
|
||||||
|
}
|
||||||
|
catch (AudioOpenError const& e) {
|
||||||
|
wxMessageBox(lagi_wxString(e.GetMessage()), L"Error loading audio",wxICON_ERROR | wxOK);
|
||||||
|
}
|
||||||
catch (const wxChar *e) {
|
catch (const wxChar *e) {
|
||||||
if (player) { delete player; player = 0; }
|
if (player) { delete player; player = 0; }
|
||||||
if (provider) { delete provider; provider = 0; }
|
if (provider) { delete provider; provider = 0; }
|
||||||
|
|
|
@ -34,16 +34,12 @@
|
||||||
/// @ingroup audio_ui
|
/// @ingroup audio_ui
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <wx/dcclient.h>
|
#include <wx/dcclient.h>
|
||||||
#include <wx/log.h>
|
|
||||||
#include <wx/menu.h>
|
#include <wx/menu.h>
|
||||||
#include <wx/settings.h>
|
#include <wx/settings.h>
|
||||||
#include <wx/tokenzr.h>
|
#include <wx/tokenzr.h>
|
||||||
|
@ -56,7 +52,6 @@
|
||||||
#include "audio_display.h"
|
#include "audio_display.h"
|
||||||
#include "audio_karaoke.h"
|
#include "audio_karaoke.h"
|
||||||
|
|
||||||
|
|
||||||
/// @brief Empty constructor
|
/// @brief Empty constructor
|
||||||
///
|
///
|
||||||
AudioKaraokeSyllable::AudioKaraokeSyllable()
|
AudioKaraokeSyllable::AudioKaraokeSyllable()
|
||||||
|
@ -66,7 +61,6 @@ AudioKaraokeSyllable::AudioKaraokeSyllable()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Copy-from-base constructor
|
/// @brief Copy-from-base constructor
|
||||||
/// @param base
|
/// @param base
|
||||||
///
|
///
|
||||||
|
@ -77,9 +71,6 @@ AudioKaraokeSyllable::AudioKaraokeSyllable(const AssKaraokeSyllable &base)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param parent
|
/// @param parent
|
||||||
///
|
///
|
||||||
|
@ -95,16 +86,12 @@ AudioKaraoke::AudioKaraoke(wxWindow *parent)
|
||||||
workDiag = 0;
|
workDiag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
///
|
///
|
||||||
AudioKaraoke::~AudioKaraoke() {
|
AudioKaraoke::~AudioKaraoke() {
|
||||||
delete workDiag;
|
delete workDiag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Load from dialogue
|
/// @brief Load from dialogue
|
||||||
/// @param _diag
|
/// @param _diag
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -149,8 +136,6 @@ bool AudioKaraoke::LoadFromDialogue(AssDialogue *_diag) {
|
||||||
return !hasKar;
|
return !hasKar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Writes line back
|
/// @brief Writes line back
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -196,8 +181,6 @@ void AudioKaraoke::Commit() {
|
||||||
LOG_D("karaoke/audio") << "returning";
|
LOG_D("karaoke/audio") << "returning";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Autosplit line
|
/// @brief Autosplit line
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -253,8 +236,6 @@ void AudioKaraoke::AutoSplit() {
|
||||||
LOG_D("karaoke/audio") << "returning";
|
LOG_D("karaoke/audio") << "returning";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Parses text to extract karaoke
|
/// @brief Parses text to extract karaoke
|
||||||
/// @param curDiag
|
/// @param curDiag
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -287,8 +268,6 @@ bool AudioKaraoke::ParseDialogue(AssDialogue *curDiag) {
|
||||||
return found_kara;
|
return found_kara;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set syllable
|
/// @brief Set syllable
|
||||||
/// @param n
|
/// @param n
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -304,7 +283,6 @@ void AudioKaraoke::SetSyllable(int n) {
|
||||||
LOG_D("karaoke/audio") << "returning";
|
LOG_D("karaoke/audio") << "returning";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
// Event table
|
// Event table
|
||||||
BEGIN_EVENT_TABLE(AudioKaraoke,wxWindow)
|
BEGIN_EVENT_TABLE(AudioKaraoke,wxWindow)
|
||||||
|
@ -313,8 +291,6 @@ BEGIN_EVENT_TABLE(AudioKaraoke,wxWindow)
|
||||||
EVT_MOUSE_EVENTS(AudioKaraoke::OnMouse)
|
EVT_MOUSE_EVENTS(AudioKaraoke::OnMouse)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Paint event
|
/// @brief Paint event
|
||||||
/// @param event
|
/// @param event
|
||||||
///
|
///
|
||||||
|
@ -425,8 +401,6 @@ void AudioKaraoke::OnPaint(wxPaintEvent &event) {
|
||||||
event.Skip();
|
event.Skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Size event
|
/// @brief Size event
|
||||||
/// @param event
|
/// @param event
|
||||||
///
|
///
|
||||||
|
@ -434,8 +408,6 @@ void AudioKaraoke::OnSize(wxSizeEvent &event) {
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Mouse event
|
/// @brief Mouse event
|
||||||
/// @param event
|
/// @param event
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -571,8 +543,6 @@ void AudioKaraoke::OnMouse(wxMouseEvent &event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get Syllable at position X
|
/// @brief Get Syllable at position X
|
||||||
/// @param x
|
/// @param x
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -590,8 +560,6 @@ int AudioKaraoke::GetSylAtX(int x) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set selection
|
/// @brief Set selection
|
||||||
/// @param start
|
/// @param start
|
||||||
/// @param end
|
/// @param end
|
||||||
|
@ -628,8 +596,6 @@ void AudioKaraoke::SetSelection(int start,int end) {
|
||||||
box->SetKaraokeButtons();
|
box->SetKaraokeButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Join syllables
|
/// @brief Join syllables
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -675,8 +641,6 @@ void AudioKaraoke::Join() {
|
||||||
LOG_D("karaoke/audio") << "returning";
|
LOG_D("karaoke/audio") << "returning";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Enter splitting-mode
|
/// @brief Enter splitting-mode
|
||||||
///
|
///
|
||||||
void AudioKaraoke::BeginSplit() {
|
void AudioKaraoke::BeginSplit() {
|
||||||
|
@ -688,8 +652,6 @@ void AudioKaraoke::BeginSplit() {
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Leave splitting-mode, committing changes
|
/// @brief Leave splitting-mode, committing changes
|
||||||
/// @param commit
|
/// @param commit
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -727,8 +689,6 @@ void AudioKaraoke::EndSplit(bool commit) {
|
||||||
LOG_D("karaoke/audio") << "returning";
|
LOG_D("karaoke/audio") << "returning";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Split a syllable using the pending_slits data
|
/// @brief Split a syllable using the pending_slits data
|
||||||
/// @param n
|
/// @param n
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -799,8 +759,6 @@ int AudioKaraoke::SplitSyl (unsigned int n) {
|
||||||
return numsplits;
|
return numsplits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Apply delta length to syllable
|
/// @brief Apply delta length to syllable
|
||||||
/// @param n
|
/// @param n
|
||||||
/// @param delta
|
/// @param delta
|
||||||
|
@ -855,8 +813,6 @@ bool AudioKaraoke::SyllableDelta(int n,int delta,int mode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Karaoke tag menu constructor
|
/// @brief Karaoke tag menu constructor
|
||||||
/// @param _kara
|
/// @param _kara
|
||||||
///
|
///
|
||||||
|
@ -884,22 +840,17 @@ AudioKaraokeTagMenu::AudioKaraokeTagMenu(AudioKaraoke *_kara)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Karaoke tag menu destructor
|
/// @brief Karaoke tag menu destructor
|
||||||
///
|
///
|
||||||
AudioKaraokeTagMenu::~AudioKaraokeTagMenu() {
|
AudioKaraokeTagMenu::~AudioKaraokeTagMenu() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
// Event table
|
// Event table
|
||||||
BEGIN_EVENT_TABLE(AudioKaraokeTagMenu,wxMenu)
|
BEGIN_EVENT_TABLE(AudioKaraokeTagMenu,wxMenu)
|
||||||
EVT_MENU_RANGE(10001, 10003, AudioKaraokeTagMenu::OnSelectItem)
|
EVT_MENU_RANGE(10001, 10003, AudioKaraokeTagMenu::OnSelectItem)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Karaoke tag menu event handler
|
/// @brief Karaoke tag menu event handler
|
||||||
/// @param event
|
/// @param event
|
||||||
///
|
///
|
||||||
|
@ -934,6 +885,3 @@ void AudioKaraokeTagMenu::OnSelectItem(wxCommandEvent &event) {
|
||||||
kara->SetSelection(firstsel, lastsel);
|
kara->SetSelection(firstsel, lastsel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,8 @@
|
||||||
/// @ingroup audio_output
|
/// @ingroup audio_output
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_ALSA
|
#ifdef WITH_ALSA
|
||||||
|
|
||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
|
@ -48,7 +46,6 @@
|
||||||
#include "frame_main.h"
|
#include "frame_main.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
///
|
///
|
||||||
AlsaPlayer::AlsaPlayer()
|
AlsaPlayer::AlsaPlayer()
|
||||||
|
|
|
@ -34,16 +34,12 @@
|
||||||
/// @ingroup audio_output
|
/// @ingroup audio_output
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_ALSA
|
#ifdef WITH_ALSA
|
||||||
|
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
|
|
||||||
#include "include/aegisub/audio_player.h"
|
#include "include/aegisub/audio_player.h"
|
||||||
#include "include/aegisub/audio_provider.h"
|
#include "include/aegisub/audio_provider.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class AlsaPlayer
|
/// @class AlsaPlayer
|
||||||
|
@ -62,7 +58,6 @@ private:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
volatile float volume;
|
volatile float volume;
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
volatile unsigned long start_frame; // first frame of playback
|
volatile unsigned long start_frame; // first frame of playback
|
||||||
|
|
||||||
|
@ -75,7 +70,6 @@ private:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
unsigned long bpf; // bytes per frame
|
unsigned long bpf; // bytes per frame
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
AudioProvider *provider;
|
AudioProvider *provider;
|
||||||
|
|
||||||
|
@ -88,7 +82,6 @@ private:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
snd_async_handler_t *pcm_callback;
|
snd_async_handler_t *pcm_callback;
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
snd_pcm_format_t sample_format;
|
snd_pcm_format_t sample_format;
|
||||||
|
|
||||||
|
@ -132,7 +125,6 @@ public:
|
||||||
void SetEndPosition(int64_t pos);
|
void SetEndPosition(int64_t pos);
|
||||||
void SetCurrentPosition(int64_t pos);
|
void SetCurrentPosition(int64_t pos);
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param vol
|
/// @param vol
|
||||||
/// @return
|
/// @return
|
||||||
|
|
|
@ -34,9 +34,6 @@
|
||||||
/// @ingroup audio_output
|
/// @ingroup audio_output
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef WITH_DIRECTSOUND
|
#ifdef WITH_DIRECTSOUND
|
||||||
|
@ -48,7 +45,6 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
///
|
///
|
||||||
DirectSoundPlayer::DirectSoundPlayer() {
|
DirectSoundPlayer::DirectSoundPlayer() {
|
||||||
|
@ -64,16 +60,12 @@ DirectSoundPlayer::DirectSoundPlayer() {
|
||||||
thread = NULL;
|
thread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
///
|
///
|
||||||
DirectSoundPlayer::~DirectSoundPlayer() {
|
DirectSoundPlayer::~DirectSoundPlayer() {
|
||||||
CloseStream();
|
CloseStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Open stream
|
/// @brief Open stream
|
||||||
///
|
///
|
||||||
void DirectSoundPlayer::OpenStream() {
|
void DirectSoundPlayer::OpenStream() {
|
||||||
|
@ -125,8 +117,6 @@ void DirectSoundPlayer::OpenStream() {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Close stream
|
/// @brief Close stream
|
||||||
///
|
///
|
||||||
void DirectSoundPlayer::CloseStream() {
|
void DirectSoundPlayer::CloseStream() {
|
||||||
|
@ -146,8 +136,6 @@ void DirectSoundPlayer::CloseStream() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Fill buffer
|
/// @brief Fill buffer
|
||||||
/// @param fill
|
/// @param fill
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -237,8 +225,6 @@ RetryLock:
|
||||||
return playPos < endPos;
|
return playPos < endPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Play
|
/// @brief Play
|
||||||
/// @param start
|
/// @param start
|
||||||
/// @param count
|
/// @param count
|
||||||
|
@ -281,8 +267,6 @@ void DirectSoundPlayer::Play(int64_t start,int64_t count) {
|
||||||
if (displayTimer && !displayTimer->IsRunning()) displayTimer->Start(15);
|
if (displayTimer && !displayTimer->IsRunning()) displayTimer->Start(15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Stop
|
/// @brief Stop
|
||||||
/// @param timerToo
|
/// @param timerToo
|
||||||
///
|
///
|
||||||
|
@ -313,8 +297,6 @@ void DirectSoundPlayer::Stop(bool timerToo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set end
|
/// @brief Set end
|
||||||
/// @param pos
|
/// @param pos
|
||||||
///
|
///
|
||||||
|
@ -322,8 +304,6 @@ void DirectSoundPlayer::SetEndPosition(int64_t pos) {
|
||||||
if (playing) endPos = pos;
|
if (playing) endPos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set current position
|
/// @brief Set current position
|
||||||
/// @param pos
|
/// @param pos
|
||||||
///
|
///
|
||||||
|
@ -332,8 +312,6 @@ void DirectSoundPlayer::SetCurrentPosition(int64_t pos) {
|
||||||
startTime = GetTickCount();
|
startTime = GetTickCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get current position
|
/// @brief Get current position
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -348,8 +326,6 @@ int64_t DirectSoundPlayer::GetCurrentPosition() {
|
||||||
return startPos + tdiff * provider->GetSampleRate() / 1000;
|
return startPos + tdiff * provider->GetSampleRate() / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Thread constructor
|
/// @brief Thread constructor
|
||||||
/// @param par
|
/// @param par
|
||||||
///
|
///
|
||||||
|
@ -358,16 +334,12 @@ DirectSoundPlayerThread::DirectSoundPlayerThread(DirectSoundPlayer *par) : wxThr
|
||||||
stopnotify = CreateEvent(NULL, true, false, NULL);
|
stopnotify = CreateEvent(NULL, true, false, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Thread destructor
|
/// @brief Thread destructor
|
||||||
///
|
///
|
||||||
DirectSoundPlayerThread::~DirectSoundPlayerThread() {
|
DirectSoundPlayerThread::~DirectSoundPlayerThread() {
|
||||||
CloseHandle(stopnotify);
|
CloseHandle(stopnotify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Thread entry point
|
/// @brief Thread entry point
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -418,8 +390,6 @@ wxThread::ExitCode DirectSoundPlayerThread::Entry() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Stop playback thread
|
/// @brief Stop playback thread
|
||||||
///
|
///
|
||||||
void DirectSoundPlayerThread::Stop() {
|
void DirectSoundPlayerThread::Stop() {
|
||||||
|
@ -429,4 +399,3 @@ void DirectSoundPlayerThread::Stop() {
|
||||||
|
|
||||||
#endif // WITH_DIRECTSOUND
|
#endif // WITH_DIRECTSOUND
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,6 @@
|
||||||
/// @ingroup audio_output
|
/// @ingroup audio_output
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#ifdef WITH_DIRECTSOUND
|
#ifdef WITH_DIRECTSOUND
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
|
@ -47,15 +44,9 @@
|
||||||
|
|
||||||
#include "include/aegisub/audio_player.h"
|
#include "include/aegisub/audio_player.h"
|
||||||
#include "include/aegisub/audio_provider.h"
|
#include "include/aegisub/audio_provider.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
|
|
||||||
//////////////
|
|
||||||
// Prototypes
|
|
||||||
class DirectSoundPlayer;
|
class DirectSoundPlayer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class DirectSoundPlayerThread
|
/// @class DirectSoundPlayerThread
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
|
@ -93,8 +84,6 @@ detect which were actually changed and act accordingly.
|
||||||
All but GetPosition() set appropriate fields and then raise the parameters changed event.
|
All but GetPosition() set appropriate fields and then raise the parameters changed event.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class DirectSoundPlayer
|
/// @class DirectSoundPlayer
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
|
@ -117,7 +106,6 @@ private:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
DWORD bufSize;
|
DWORD bufSize;
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
volatile int64_t playPos;
|
volatile int64_t playPos;
|
||||||
|
|
||||||
|
@ -130,7 +118,6 @@ private:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
DWORD startTime;
|
DWORD startTime;
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
IDirectSound8 *directSound;
|
IDirectSound8 *directSound;
|
||||||
|
|
||||||
|
@ -139,7 +126,6 @@ private:
|
||||||
|
|
||||||
bool FillBuffer(bool fill);
|
bool FillBuffer(bool fill);
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
DirectSoundPlayerThread *thread;
|
DirectSoundPlayerThread *thread;
|
||||||
|
|
||||||
|
@ -158,7 +144,6 @@ public:
|
||||||
///
|
///
|
||||||
bool IsPlaying() { return playing; }
|
bool IsPlaying() { return playing; }
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -172,7 +157,6 @@ public:
|
||||||
void SetEndPosition(int64_t pos);
|
void SetEndPosition(int64_t pos);
|
||||||
void SetCurrentPosition(int64_t pos);
|
void SetCurrentPosition(int64_t pos);
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param vol
|
/// @param vol
|
||||||
/// @return
|
/// @return
|
||||||
|
|
|
@ -44,17 +44,6 @@
|
||||||
#include "frame_main.h"
|
#include "frame_main.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
|
||||||
#include <al.h>
|
|
||||||
#include <alc.h>
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
#include <OpenAL/AL.h>
|
|
||||||
#include <OpenAL/ALC.h>
|
|
||||||
#else
|
|
||||||
#include <AL/al.h>
|
|
||||||
#include <AL/alc.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Auto-link to OpenAL lib for MSVC
|
// Auto-link to OpenAL lib for MSVC
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma comment(lib, "openal32.lib")
|
#pragma comment(lib, "openal32.lib")
|
||||||
|
@ -78,8 +67,6 @@ OpenALPlayer::~OpenALPlayer()
|
||||||
CloseStream();
|
CloseStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Open stream
|
/// @brief Open stream
|
||||||
///
|
///
|
||||||
void OpenALPlayer::OpenStream()
|
void OpenALPlayer::OpenStream()
|
||||||
|
@ -135,8 +122,6 @@ void OpenALPlayer::OpenStream()
|
||||||
open = true;
|
open = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Close stream
|
/// @brief Close stream
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -155,8 +140,6 @@ void OpenALPlayer::CloseStream()
|
||||||
open = false;
|
open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Play
|
/// @brief Play
|
||||||
/// @param start
|
/// @param start
|
||||||
/// @param count
|
/// @param count
|
||||||
|
@ -192,8 +175,6 @@ void OpenALPlayer::Play(int64_t start,int64_t count)
|
||||||
if (displayTimer && !displayTimer->IsRunning()) displayTimer->Start(15);
|
if (displayTimer && !displayTimer->IsRunning()) displayTimer->Start(15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Stop
|
/// @brief Stop
|
||||||
/// @param timerToo
|
/// @param timerToo
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -219,8 +200,6 @@ void OpenALPlayer::Stop(bool timerToo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param count
|
/// @param count
|
||||||
///
|
///
|
||||||
|
@ -261,8 +240,6 @@ void OpenALPlayer::FillBuffers(ALsizei count)
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
///
|
///
|
||||||
void OpenALPlayer::Notify()
|
void OpenALPlayer::Notify()
|
||||||
|
@ -300,8 +277,6 @@ void OpenALPlayer::Notify()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -310,8 +285,6 @@ bool OpenALPlayer::IsPlaying()
|
||||||
return playing;
|
return playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set end
|
/// @brief Set end
|
||||||
/// @param pos
|
/// @param pos
|
||||||
///
|
///
|
||||||
|
@ -320,8 +293,6 @@ void OpenALPlayer::SetEndPosition(int64_t pos)
|
||||||
end_frame = pos;
|
end_frame = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set current position
|
/// @brief Set current position
|
||||||
/// @param pos
|
/// @param pos
|
||||||
///
|
///
|
||||||
|
@ -330,8 +301,6 @@ void OpenALPlayer::SetCurrentPosition(int64_t pos)
|
||||||
cur_frame = pos;
|
cur_frame = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -340,8 +309,6 @@ int64_t OpenALPlayer::GetStartPosition()
|
||||||
return start_frame;
|
return start_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -350,8 +317,6 @@ int64_t OpenALPlayer::GetEndPosition()
|
||||||
return end_frame;
|
return end_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get current position
|
/// @brief Get current position
|
||||||
///
|
///
|
||||||
int64_t OpenALPlayer::GetCurrentPosition()
|
int64_t OpenALPlayer::GetCurrentPosition()
|
||||||
|
@ -362,5 +327,4 @@ int64_t OpenALPlayer::GetCurrentPosition()
|
||||||
return buffers_played * buffer_length + start_frame + extra * samplerate / 1000;
|
return buffers_played * buffer_length + start_frame + extra * samplerate / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // WITH_OPENAL
|
#endif // WITH_OPENAL
|
||||||
|
|
|
@ -34,11 +34,9 @@
|
||||||
/// @ingroup audio_output
|
/// @ingroup audio_output
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_OPENAL
|
#ifdef WITH_OPENAL
|
||||||
#include "include/aegisub/audio_player.h"
|
#include "include/aegisub/audio_player.h"
|
||||||
#include "include/aegisub/audio_provider.h"
|
#include "include/aegisub/audio_provider.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
#include <al.h>
|
#include <al.h>
|
||||||
|
@ -68,7 +66,6 @@ private:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
volatile float volume;
|
volatile float volume;
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
static const ALsizei num_buffers = 8;
|
static const ALsizei num_buffers = 8;
|
||||||
|
|
||||||
|
@ -78,7 +75,6 @@ private:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
ALsizei samplerate;
|
ALsizei samplerate;
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
volatile unsigned long start_frame; // first frame of playback
|
volatile unsigned long start_frame; // first frame of playback
|
||||||
|
|
||||||
|
@ -91,7 +87,6 @@ private:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
unsigned long bpf; // bytes per frame
|
unsigned long bpf; // bytes per frame
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
AudioProvider *provider;
|
AudioProvider *provider;
|
||||||
|
|
||||||
|
@ -107,7 +102,6 @@ private:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
ALuint source; // playback source
|
ALuint source; // playback source
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
ALsizei buf_first_free; // index into buffers, first free (unqueued) buffer
|
ALsizei buf_first_free; // index into buffers, first free (unqueued) buffer
|
||||||
|
|
||||||
|
@ -145,7 +139,6 @@ public:
|
||||||
void SetEndPosition(int64_t pos);
|
void SetEndPosition(int64_t pos);
|
||||||
void SetCurrentPosition(int64_t pos);
|
void SetCurrentPosition(int64_t pos);
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param vol
|
/// @param vol
|
||||||
/// @return
|
/// @return
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
/// @ingroup audio_output
|
/// @ingroup audio_output
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef WITH_OSS
|
#ifdef WITH_OSS
|
||||||
|
@ -45,7 +44,6 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
///
|
///
|
||||||
OSSPlayer::OSSPlayer()
|
OSSPlayer::OSSPlayer()
|
||||||
|
@ -58,8 +56,6 @@ OSSPlayer::OSSPlayer()
|
||||||
thread = 0;
|
thread = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
///
|
///
|
||||||
OSSPlayer::~OSSPlayer()
|
OSSPlayer::~OSSPlayer()
|
||||||
|
@ -67,8 +63,6 @@ OSSPlayer::~OSSPlayer()
|
||||||
CloseStream();
|
CloseStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Open stream
|
/// @brief Open stream
|
||||||
///
|
///
|
||||||
void OSSPlayer::OpenStream()
|
void OSSPlayer::OpenStream()
|
||||||
|
@ -125,8 +119,6 @@ void OSSPlayer::OpenStream()
|
||||||
open = true;
|
open = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Close stream
|
/// @brief Close stream
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -141,8 +133,6 @@ void OSSPlayer::CloseStream()
|
||||||
open = false;
|
open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Play
|
/// @brief Play
|
||||||
/// @param start
|
/// @param start
|
||||||
/// @param count
|
/// @param count
|
||||||
|
@ -163,8 +153,6 @@ void OSSPlayer::Play(int64_t start, int64_t count)
|
||||||
playing = true;
|
playing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Stop
|
/// @brief Stop
|
||||||
/// @param timerToo
|
/// @param timerToo
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -198,8 +186,6 @@ void OSSPlayer::Stop(bool timerToo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -208,8 +194,6 @@ bool OSSPlayer::IsPlaying()
|
||||||
return playing;
|
return playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set end
|
/// @brief Set end
|
||||||
/// @param pos
|
/// @param pos
|
||||||
///
|
///
|
||||||
|
@ -225,8 +209,6 @@ void OSSPlayer::SetEndPosition(int64_t pos)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set current position
|
/// @brief Set current position
|
||||||
/// @param pos
|
/// @param pos
|
||||||
///
|
///
|
||||||
|
@ -235,8 +217,6 @@ void OSSPlayer::SetCurrentPosition(int64_t pos)
|
||||||
cur_frame = start_frame = pos;
|
cur_frame = start_frame = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -245,8 +225,6 @@ int64_t OSSPlayer::GetStartPosition()
|
||||||
return start_frame;
|
return start_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -255,8 +233,6 @@ int64_t OSSPlayer::GetEndPosition()
|
||||||
return end_frame;
|
return end_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get current position
|
/// @brief Get current position
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -305,8 +281,6 @@ int64_t OSSPlayer::GetCurrentPosition()
|
||||||
return cur_frame;
|
return cur_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Thread constructor
|
/// @brief Thread constructor
|
||||||
/// @param par
|
/// @param par
|
||||||
///
|
///
|
||||||
|
@ -338,6 +312,4 @@ wxThread::ExitCode OSSPlayerThread::Entry() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // WITH_OSS
|
#endif // WITH_OSS
|
||||||
|
|
|
@ -52,7 +52,6 @@
|
||||||
|
|
||||||
#include "include/aegisub/audio_player.h"
|
#include "include/aegisub/audio_player.h"
|
||||||
#include "include/aegisub/audio_provider.h"
|
#include "include/aegisub/audio_provider.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
class OSSPlayer;
|
class OSSPlayer;
|
||||||
|
|
||||||
|
@ -73,8 +72,6 @@ public:
|
||||||
wxThread::ExitCode Entry();
|
wxThread::ExitCode Entry();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class OSSPlayer
|
/// @class OSSPlayer
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
|
|
|
@ -34,13 +34,13 @@
|
||||||
/// @ingroup audio_output
|
/// @ingroup audio_output
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_PORTAUDIO
|
#ifdef WITH_PORTAUDIO
|
||||||
|
|
||||||
#include "include/aegisub/audio_player.h"
|
#include "include/aegisub/audio_player.h"
|
||||||
#include "include/aegisub/audio_provider.h"
|
#include "include/aegisub/audio_provider.h"
|
||||||
#include "utils.h"
|
|
||||||
extern "C" {
|
|
||||||
|
"C" {
|
||||||
#include <portaudio.h>
|
#include <portaudio.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,15 +35,10 @@
|
||||||
///
|
///
|
||||||
|
|
||||||
#ifdef WITH_PULSEAUDIO
|
#ifdef WITH_PULSEAUDIO
|
||||||
#ifndef AGI_PRE
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <pulse/pulseaudio.h>
|
#include <pulse/pulseaudio.h>
|
||||||
|
|
||||||
#include "include/aegisub/audio_player.h"
|
#include "include/aegisub/audio_player.h"
|
||||||
#include "include/aegisub/audio_provider.h"
|
#include "include/aegisub/audio_provider.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
class PulseAudioPlayer;
|
class PulseAudioPlayer;
|
||||||
|
|
||||||
|
|
|
@ -178,66 +178,69 @@ void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count,
|
||||||
///
|
///
|
||||||
AudioProvider *AudioProviderFactory::GetProvider(wxString filename, int cache) {
|
AudioProvider *AudioProviderFactory::GetProvider(wxString filename, int cache) {
|
||||||
AudioProvider *provider = NULL;
|
AudioProvider *provider = NULL;
|
||||||
|
bool found = false;
|
||||||
|
std::string msg;
|
||||||
|
|
||||||
if (!OPT_GET("Provider/Audio/PCM/Disable")->GetBool()) {
|
if (!OPT_GET("Provider/Audio/PCM/Disable")->GetBool()) {
|
||||||
// Try a PCM provider first
|
// Try a PCM provider first
|
||||||
provider = CreatePCMAudioProvider(filename);
|
try {
|
||||||
if (provider) {
|
provider = CreatePCMAudioProvider(filename);
|
||||||
if (provider->GetBytesPerSample() == 2 && provider->GetSampleRate() >= 32000 && provider->GetChannels() == 1)
|
}
|
||||||
return provider;
|
catch (agi::FileNotFoundError const& err) {
|
||||||
else {
|
msg = "PCM audio provider: " + err.GetMessage() + " not found.\n";
|
||||||
return CreateConvertAudioProvider(provider);
|
}
|
||||||
|
catch (AudioOpenError const& err) {
|
||||||
|
found = true;
|
||||||
|
msg += err.GetMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!provider) {
|
||||||
|
std::vector<std::string> list = GetClasses(OPT_GET("Audio/Provider")->GetString());
|
||||||
|
if (list.empty()) throw AudioOpenError("No audio providers are available.");
|
||||||
|
|
||||||
|
for (unsigned int i=0;i<list.size();i++) {
|
||||||
|
try {
|
||||||
|
provider = Create(list[i], filename);
|
||||||
|
if (provider) break;
|
||||||
|
}
|
||||||
|
catch (agi::FileNotFoundError const& err) {
|
||||||
|
msg += list[i] + ": " + err.GetMessage() + " not found.\n";
|
||||||
|
}
|
||||||
|
catch (AudioOpenError const& err) {
|
||||||
|
found = true;
|
||||||
|
msg += list[i] + ": " + err.GetMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!provider) {
|
||||||
// List of providers
|
if (found) {
|
||||||
std::vector<std::string> list = GetClasses(OPT_GET("Audio/Provider")->GetString());
|
throw AudioOpenError(msg);
|
||||||
|
}
|
||||||
if (list.empty()) throw _T("No audio providers are available.");
|
else {
|
||||||
|
throw agi::FileNotFoundError(STD_STR(filename));
|
||||||
// Get provider
|
|
||||||
wxString error;
|
|
||||||
for (unsigned int i=0;i<list.size();i++) {
|
|
||||||
try {
|
|
||||||
provider = Create(list[i], filename);
|
|
||||||
if (provider) break;
|
|
||||||
}
|
}
|
||||||
catch (wxString err) { error += list[i] + _T(" factory: ") + err + _T("\n"); }
|
|
||||||
catch (const wxChar *err) { error += list[i] + _T(" factory: ") + wxString(err) + _T("\n"); }
|
|
||||||
catch (...) { error += list[i] + _T(" factory: Unknown error\n"); }
|
|
||||||
}
|
}
|
||||||
|
bool needsCache = provider->NeedsCache();
|
||||||
|
|
||||||
// Failed
|
// Give it a converter if needed
|
||||||
if (!provider) throw error;
|
|
||||||
|
|
||||||
// Give it a conversor if needed
|
|
||||||
if (provider->GetBytesPerSample() != 2 || provider->GetSampleRate() < 32000 || provider->GetChannels() != 1)
|
if (provider->GetBytesPerSample() != 2 || provider->GetSampleRate() < 32000 || provider->GetChannels() != 1)
|
||||||
provider = CreateConvertAudioProvider(provider);
|
provider = CreateConvertAudioProvider(provider);
|
||||||
|
|
||||||
// Change provider to RAM/HD cache if needed
|
// Change provider to RAM/HD cache if needed
|
||||||
if (cache == -1) cache = OPT_GET("Audio/Cache/Type")->GetInt();
|
if (cache == -1) cache = OPT_GET("Audio/Cache/Type")->GetInt();
|
||||||
if (cache) {
|
if (!cache || !needsCache) {
|
||||||
AudioProvider *final = NULL;
|
return provider;
|
||||||
|
|
||||||
// Convert to RAM
|
|
||||||
if (cache == 1) final = new RAMAudioProvider(provider);
|
|
||||||
|
|
||||||
// Convert to HD
|
|
||||||
if (cache == 2) final = new HDAudioProvider(provider);
|
|
||||||
|
|
||||||
// Reassign
|
|
||||||
if (final) {
|
|
||||||
delete provider;
|
|
||||||
return final;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return provider;
|
// Convert to RAM
|
||||||
|
if (cache == 1) return new RAMAudioProvider(provider);
|
||||||
|
|
||||||
|
// Convert to HD
|
||||||
|
if (cache == 2) return new HDAudioProvider(provider);
|
||||||
|
|
||||||
|
throw AudioOpenError("Unknown caching method");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Register all providers
|
/// @brief Register all providers
|
||||||
///
|
///
|
||||||
void AudioProviderFactory::RegisterProviders() {
|
void AudioProviderFactory::RegisterProviders() {
|
||||||
|
|
|
@ -34,14 +34,10 @@
|
||||||
/// @ingroup audio_input
|
/// @ingroup audio_input
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef WITH_AVISYNTH
|
#ifdef WITH_AVISYNTH
|
||||||
|
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <Mmreg.h>
|
#include <Mmreg.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -56,100 +52,59 @@
|
||||||
#include "standard_paths.h"
|
#include "standard_paths.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param _filename
|
/// @param _filename
|
||||||
///
|
///
|
||||||
AvisynthAudioProvider::AvisynthAudioProvider(wxString _filename) {
|
AvisynthAudioProvider::AvisynthAudioProvider(wxString filename) try : filename(filename) {
|
||||||
filename = _filename;
|
|
||||||
|
|
||||||
try {
|
|
||||||
OpenAVSAudio();
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
Unload();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
|
||||||
///
|
|
||||||
AvisynthAudioProvider::~AvisynthAudioProvider() {
|
|
||||||
Unload();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Unload audio
|
|
||||||
///
|
|
||||||
void AvisynthAudioProvider::Unload() {
|
|
||||||
// Clean up avisynth
|
|
||||||
clip = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Load audio from avisynth
|
|
||||||
///
|
|
||||||
void AvisynthAudioProvider::OpenAVSAudio() {
|
|
||||||
// Set variables
|
|
||||||
AVSValue script;
|
AVSValue script;
|
||||||
|
|
||||||
// Prepare avisynth
|
|
||||||
wxMutexLocker lock(AviSynthMutex);
|
wxMutexLocker lock(AviSynthMutex);
|
||||||
|
|
||||||
try {
|
wxFileName fn(filename);
|
||||||
// Include
|
if (!fn.FileExists())
|
||||||
if (filename.EndsWith(_T(".avs"))) {
|
throw agi::FileNotFoundError(STD_STR(filename));
|
||||||
wxFileName fn(filename);
|
|
||||||
char *fname = env->SaveString(fn.GetShortPath().mb_str(csConvLocal));
|
// Include
|
||||||
script = env->Invoke("Import", fname);
|
if (filename.EndsWith(_T(".avs"))) {
|
||||||
|
char *fname = env->SaveString(fn.GetShortPath().mb_str(csConvLocal));
|
||||||
|
script = env->Invoke("Import", fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use DirectShowSource
|
||||||
|
else {
|
||||||
|
const char * argnames[3] = { 0, "video", "audio" };
|
||||||
|
AVSValue args[3] = { env->SaveString(fn.GetShortPath().mb_str(csConvLocal)), false, true };
|
||||||
|
|
||||||
|
// Load DirectShowSource.dll from app dir if it exists
|
||||||
|
wxFileName dsspath(StandardPaths::DecodePath(_T("?data/DirectShowSource.dll")));
|
||||||
|
if (dsspath.FileExists()) {
|
||||||
|
env->Invoke("LoadPlugin",env->SaveString(dsspath.GetShortPath().mb_str(csConvLocal)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use DirectShowSource
|
// Load audio with DSS if it exists
|
||||||
|
if (env->FunctionExists("DirectShowSource")) {
|
||||||
|
script = env->Invoke("DirectShowSource", AVSValue(args,3),argnames);
|
||||||
|
}
|
||||||
|
// Otherwise fail
|
||||||
else {
|
else {
|
||||||
wxFileName fn(filename);
|
throw AudioOpenError("No suitable audio source filter found. Try placing DirectShowSource.dll in the Aegisub application directory.");
|
||||||
const char * argnames[3] = { 0, "video", "audio" };
|
|
||||||
AVSValue args[3] = { env->SaveString(fn.GetShortPath().mb_str(csConvLocal)), false, true };
|
|
||||||
|
|
||||||
// Load DirectShowSource.dll from app dir if it exists
|
|
||||||
wxFileName dsspath(StandardPaths::DecodePath(_T("?data/DirectShowSource.dll")));
|
|
||||||
if (dsspath.FileExists()) {
|
|
||||||
env->Invoke("LoadPlugin",env->SaveString(dsspath.GetShortPath().mb_str(csConvLocal)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load audio with DSS if it exists
|
|
||||||
if (env->FunctionExists("DirectShowSource")) {
|
|
||||||
script = env->Invoke("DirectShowSource", AVSValue(args,3),argnames);
|
|
||||||
}
|
|
||||||
// Otherwise fail
|
|
||||||
else {
|
|
||||||
throw AvisynthError("No suitable audio source filter found. Try placing DirectShowSource.dll in the Aegisub application directory.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadFromClip(script);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (AvisynthError &err) {
|
LoadFromClip(script);
|
||||||
throw wxString::Format(_T("AviSynth error: %s"), wxString(err.msg,csConvLocal));
|
}
|
||||||
}
|
catch (AvisynthError &err) {
|
||||||
|
throw AudioOpenError("Avisynth error: " + std::string(err.msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Read from environment
|
/// @brief Read from environment
|
||||||
/// @param _clip
|
/// @param _clip
|
||||||
///
|
///
|
||||||
void AvisynthAudioProvider::LoadFromClip(AVSValue _clip) {
|
void AvisynthAudioProvider::LoadFromClip(AVSValue _clip) {
|
||||||
// Prepare avisynth
|
|
||||||
AVSValue script;
|
AVSValue script;
|
||||||
|
|
||||||
// Check if it has audio
|
// Check if it has audio
|
||||||
VideoInfo vi = _clip.AsClip()->GetVideoInfo();
|
VideoInfo vi = _clip.AsClip()->GetVideoInfo();
|
||||||
if (!vi.HasAudio()) throw wxString(_T("No audio found."));
|
if (!vi.HasAudio()) throw AudioOpenError("No audio found.");
|
||||||
|
|
||||||
// Convert to one channel
|
// Convert to one channel
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
|
@ -178,20 +133,9 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue _clip) {
|
||||||
sample_rate = vi.SamplesPerSecond();
|
sample_rate = vi.SamplesPerSecond();
|
||||||
bytes_per_sample = vi.BytesPerAudioSample();
|
bytes_per_sample = vi.BytesPerAudioSample();
|
||||||
|
|
||||||
// Set
|
|
||||||
clip = tempclip;
|
clip = tempclip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get filename
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
wxString AvisynthAudioProvider::GetFilename() {
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get audio
|
/// @brief Get audio
|
||||||
/// @param buf
|
/// @param buf
|
||||||
/// @param start
|
/// @param start
|
||||||
|
@ -223,7 +167,4 @@ void AvisynthAudioProvider::GetAudio(void *buf, int64_t start, int64_t count) {
|
||||||
clip->GetAudio(buf,start,count,env);
|
clip->GetAudio(buf,start,count,env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
///
|
///
|
||||||
|
|
||||||
#ifdef WITH_AVISYNTH
|
#ifdef WITH_AVISYNTH
|
||||||
#include <Mmreg.h>
|
|
||||||
#include "include/aegisub/audio_provider.h"
|
#include "include/aegisub/audio_provider.h"
|
||||||
#include "avisynth_wrap.h"
|
#include "avisynth_wrap.h"
|
||||||
|
|
||||||
|
@ -46,8 +45,6 @@
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class AvisynthAudioProvider : public AudioProvider, public AviSynthWrapper {
|
class AvisynthAudioProvider : public AudioProvider, public AviSynthWrapper {
|
||||||
private:
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
wxString filename;
|
wxString filename;
|
||||||
|
|
||||||
|
@ -55,21 +52,18 @@ private:
|
||||||
PClip clip;
|
PClip clip;
|
||||||
|
|
||||||
void LoadFromClip(AVSValue clip);
|
void LoadFromClip(AVSValue clip);
|
||||||
void OpenAVSAudio();
|
|
||||||
void SetFile();
|
void SetFile();
|
||||||
void Unload();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AvisynthAudioProvider(wxString _filename);
|
AvisynthAudioProvider(wxString _filename);
|
||||||
~AvisynthAudioProvider();
|
|
||||||
|
|
||||||
wxString GetFilename();
|
|
||||||
|
|
||||||
|
wxString GetFilename() { return filename; }
|
||||||
|
|
||||||
/// @brief Only exists for x86 Windows, always delivers machine (little) endian
|
/// @brief Only exists for x86 Windows, always delivers machine (little) endian
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
bool AreSamplesNativeEndian() const { return true; }
|
bool AreSamplesNativeEndian() const { return true; }
|
||||||
|
bool NeedsCache() const { return true; }
|
||||||
|
|
||||||
void GetAudio(void *buf, int64_t start, int64_t count);
|
void GetAudio(void *buf, int64_t start, int64_t count);
|
||||||
void GetWaveForm(int *min,int *peak,int64_t start,int w,int h,int samples,float scale);
|
void GetWaveForm(int *min,int *peak,int64_t start,int w,int h,int samples,float scale);
|
||||||
|
|
|
@ -34,9 +34,6 @@
|
||||||
/// @ingroup audio_input
|
/// @ingroup audio_input
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "aegisub_endian.h"
|
#include "aegisub_endian.h"
|
||||||
|
@ -47,8 +44,7 @@
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param src
|
/// @param src
|
||||||
///
|
///
|
||||||
ConvertAudioProvider::ConvertAudioProvider(AudioProvider *src) {
|
ConvertAudioProvider::ConvertAudioProvider(AudioProvider *src) : source(src) {
|
||||||
source = src;
|
|
||||||
channels = source->GetChannels();
|
channels = source->GetChannels();
|
||||||
num_samples = source->GetNumSamples();
|
num_samples = source->GetNumSamples();
|
||||||
sample_rate = source->GetSampleRate();
|
sample_rate = source->GetSampleRate();
|
||||||
|
@ -61,16 +57,6 @@ ConvertAudioProvider::ConvertAudioProvider(AudioProvider *src) {
|
||||||
num_samples *= sampleMult;
|
num_samples *= sampleMult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
|
||||||
///
|
|
||||||
ConvertAudioProvider::~ConvertAudioProvider() {
|
|
||||||
delete source;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Convert to 16-bit
|
/// @brief Convert to 16-bit
|
||||||
/// @param src
|
/// @param src
|
||||||
/// @param dst
|
/// @param dst
|
||||||
|
@ -82,7 +68,6 @@ void ConvertAudioProvider::Make16Bit(const char *src, short *dst, int64_t count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////
|
//////////////////////
|
||||||
// Change sample rate
|
// Change sample rate
|
||||||
// This requres 16-bit input
|
// This requres 16-bit input
|
||||||
|
@ -134,35 +119,21 @@ void ConvertAudioProvider::ChangeSampleRate(const short *src, short *dst, int64_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
struct NullSampleConverter {
|
struct NullSampleConverter {
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
/// @param val
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
inline short operator()(const short val) const {
|
inline short operator()(const short val) const {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
struct EndianSwapSampleConverter {
|
struct EndianSwapSampleConverter {
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
/// @param val
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
inline short operator()(const short val) const {
|
inline short operator()(const short val) const {
|
||||||
return (short)Endian::Reverse((uint16_t)val);
|
return (short)Endian::Reverse((uint16_t)val);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get audio
|
/// @brief Get audio
|
||||||
/// @param destination
|
/// @param destination
|
||||||
/// @param start
|
/// @param start
|
||||||
|
@ -234,7 +205,7 @@ AudioProvider *CreateConvertAudioProvider(AudioProvider *source_provider) {
|
||||||
{
|
{
|
||||||
// @todo add support for more bitdepths (i.e. 24- and 32-bit audio)
|
// @todo add support for more bitdepths (i.e. 24- and 32-bit audio)
|
||||||
if (provider->GetBytesPerSample() > 2)
|
if (provider->GetBytesPerSample() > 2)
|
||||||
throw _T("Audio format converter: audio with bitdepths greater than 16 bits/sample is currently unsupported");
|
AudioOpenError("Audio format converter: audio with bitdepths greater than 16 bits/sample is currently unsupported");
|
||||||
|
|
||||||
provider = new ConvertAudioProvider(provider);
|
provider = new ConvertAudioProvider(provider);
|
||||||
}
|
}
|
||||||
|
@ -247,5 +218,3 @@ AudioProvider *CreateConvertAudioProvider(AudioProvider *source_provider) {
|
||||||
|
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
|
|
||||||
#include "include/aegisub/audio_provider.h"
|
#include "include/aegisub/audio_provider.h"
|
||||||
|
|
||||||
|
#ifndef AGI_PRE
|
||||||
|
#include <tr1/memory>
|
||||||
|
#endif
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class ConvertAudioProvider
|
/// @class ConvertAudioProvider
|
||||||
|
@ -43,32 +46,24 @@
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class ConvertAudioProvider : public AudioProvider {
|
class ConvertAudioProvider : public AudioProvider {
|
||||||
private:
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
int sampleMult;
|
int sampleMult;
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
AudioProvider *source;
|
std::tr1::shared_ptr<AudioProvider> source;
|
||||||
void Make16Bit(const char *src, short *dst, int64_t count);
|
void Make16Bit(const char *src, short *dst, int64_t count);
|
||||||
template<class SampleConverter>
|
template<class SampleConverter>
|
||||||
void ChangeSampleRate(const short *src, short *dst, int64_t count, const SampleConverter &converter);
|
void ChangeSampleRate(const short *src, short *dst, int64_t count, const SampleConverter &converter);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConvertAudioProvider(AudioProvider *source);
|
ConvertAudioProvider(AudioProvider *source);
|
||||||
~ConvertAudioProvider();
|
|
||||||
|
|
||||||
|
/// By its nature, the ConvertAudioProvider always delivers machine endian.
|
||||||
/// @brief // That's one of the points of it! // By its nature, the ConvertAudioProvider always delivers machine endian:
|
/// That's one of the points of it!
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
bool AreSamplesNativeEndian() const { return true; }
|
bool AreSamplesNativeEndian() const { return true; }
|
||||||
|
|
||||||
void GetAudio(void *buf, int64_t start, int64_t count);
|
void GetAudio(void *buf, int64_t start, int64_t count);
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
///
|
|
||||||
wxString GetFilename() { return source->GetFilename(); }
|
wxString GetFilename() { return source->GetFilename(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param source
|
/// @param source
|
||||||
///
|
///
|
||||||
DownmixingAudioProvider::DownmixingAudioProvider(AudioProvider *source) {
|
DownmixingAudioProvider::DownmixingAudioProvider(AudioProvider *source) : provider(source) {
|
||||||
filename = source->GetFilename();
|
filename = source->GetFilename();
|
||||||
channels = 1; // target
|
channels = 1; // target
|
||||||
src_channels = source->GetChannels();
|
src_channels = source->GetChannels();
|
||||||
|
@ -53,23 +53,12 @@ DownmixingAudioProvider::DownmixingAudioProvider(AudioProvider *source) {
|
||||||
bytes_per_sample = source->GetBytesPerSample();
|
bytes_per_sample = source->GetBytesPerSample();
|
||||||
sample_rate = source->GetSampleRate();
|
sample_rate = source->GetSampleRate();
|
||||||
|
|
||||||
// We now own this
|
|
||||||
provider = source;
|
|
||||||
|
|
||||||
if (!(bytes_per_sample == 1 || bytes_per_sample == 2))
|
if (!(bytes_per_sample == 1 || bytes_per_sample == 2))
|
||||||
throw _T("Downmixing Audio Provider: Can only downmix 8 and 16 bit audio");
|
throw AudioOpenError("Downmixing Audio Provider: Can only downmix 8 and 16 bit audio");
|
||||||
if (!source->AreSamplesNativeEndian())
|
if (!source->AreSamplesNativeEndian())
|
||||||
throw _T("Downmixing Audio Provider: Source must have machine endian samples");
|
throw AudioOpenError("Downmixing Audio Provider: Source must have machine endian samples");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
|
||||||
///
|
|
||||||
DownmixingAudioProvider::~DownmixingAudioProvider() {
|
|
||||||
delete provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Actual work happens here
|
/// @brief Actual work happens here
|
||||||
/// @param buf
|
/// @param buf
|
||||||
/// @param start
|
/// @param start
|
||||||
|
@ -95,7 +84,13 @@ void DownmixingAudioProvider::GetAudio(void *buf, int64_t start, int64_t count)
|
||||||
// a pre-allocced block of memory...?
|
// a pre-allocced block of memory...?
|
||||||
char *tmp = new char[count*bytes_per_sample*src_channels];
|
char *tmp = new char[count*bytes_per_sample*src_channels];
|
||||||
|
|
||||||
provider->GetAudio(tmp, start, count);
|
try {
|
||||||
|
provider->GetAudio(tmp, start, count);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
delete tmp;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
// Now downmix
|
// Now downmix
|
||||||
// Just average the samples over the channels (really bad if they're out of phase!)
|
// Just average the samples over the channels (really bad if they're out of phase!)
|
||||||
|
@ -128,5 +123,3 @@ void DownmixingAudioProvider::GetAudio(void *buf, int64_t start, int64_t count)
|
||||||
// Done downmixing, free the work buffer
|
// Done downmixing, free the work buffer
|
||||||
delete[] tmp;
|
delete[] tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,11 @@
|
||||||
/// @ingroup audio_input
|
/// @ingroup audio_input
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
#include "include/aegisub/audio_provider.h"
|
#include "include/aegisub/audio_provider.h"
|
||||||
|
|
||||||
|
#ifndef AGI_PRE
|
||||||
|
#include <tr1/memory>
|
||||||
|
#endif
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class DownmixingAudioProvider
|
/// @class DownmixingAudioProvider
|
||||||
|
@ -44,20 +46,14 @@
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class DownmixingAudioProvider : public AudioProvider {
|
class DownmixingAudioProvider : public AudioProvider {
|
||||||
private:
|
std::tr1::shared_ptr<AudioProvider> provider;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
AudioProvider *provider;
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
int src_channels;
|
int src_channels;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DownmixingAudioProvider(AudioProvider *source);
|
DownmixingAudioProvider(AudioProvider *source);
|
||||||
~DownmixingAudioProvider();
|
|
||||||
|
|
||||||
|
/// @brief Downmixing requires samples to be native endian beforehand
|
||||||
/// @brief // Downmixing requires samples to be native endian beforehand
|
|
||||||
///
|
///
|
||||||
bool AreSamplesNativeEndian() const { return true; }
|
bool AreSamplesNativeEndian() const { return true; }
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,6 @@
|
||||||
/// @ingroup audio_input
|
/// @ingroup audio_input
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "audio_provider_dummy.h"
|
#include "audio_provider_dummy.h"
|
||||||
|
@ -55,15 +52,11 @@ DummyAudioProvider::DummyAudioProvider(unsigned long dur_ms, bool _noise) {
|
||||||
num_samples = (int64_t)dur_ms * sample_rate / 1000;
|
num_samples = (int64_t)dur_ms * sample_rate / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
///
|
///
|
||||||
DummyAudioProvider::~DummyAudioProvider() {
|
DummyAudioProvider::~DummyAudioProvider() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get audio
|
/// @brief Get audio
|
||||||
/// @param buf
|
/// @param buf
|
||||||
/// @param start
|
/// @param start
|
||||||
|
@ -81,5 +74,3 @@ void DummyAudioProvider::GetAudio(void *buf, int64_t start, int64_t count) {
|
||||||
*workbuf++ = 0;
|
*workbuf++ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,6 @@
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class DummyAudioProvider : public AudioProvider {
|
class DummyAudioProvider : public AudioProvider {
|
||||||
private:
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
bool noise;
|
bool noise;
|
||||||
|
|
||||||
|
@ -51,10 +49,6 @@ public:
|
||||||
DummyAudioProvider(unsigned long dur_ms, bool _noise);
|
DummyAudioProvider(unsigned long dur_ms, bool _noise);
|
||||||
~DummyAudioProvider();
|
~DummyAudioProvider();
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
///
|
|
||||||
bool AreSamplesNativeEndian() const { return true; }
|
bool AreSamplesNativeEndian() const { return true; }
|
||||||
|
|
||||||
void GetAudio(void *buf, int64_t start, int64_t count);
|
void GetAudio(void *buf, int64_t start, int64_t count);
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,8 +38,6 @@
|
||||||
|
|
||||||
#ifdef WITH_FFMPEGSOURCE
|
#ifdef WITH_FFMPEGSOURCE
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
|
@ -49,22 +47,24 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "audio_provider_ffmpegsource.h"
|
#include "audio_provider_ffmpegsource.h"
|
||||||
#include "include/aegisub/aegisub.h"
|
#include "compat.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param filename
|
/// @param filename
|
||||||
///
|
///
|
||||||
FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename) {
|
FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename)
|
||||||
COMInited = false;
|
: AudioSource(NULL)
|
||||||
|
, COMInited(false)
|
||||||
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||||
if (SUCCEEDED(res))
|
if (SUCCEEDED(res))
|
||||||
COMInited = true;
|
COMInited = true;
|
||||||
else if (res != RPC_E_CHANGED_MODE)
|
else if (res != RPC_E_CHANGED_MODE)
|
||||||
throw _T("FFmpegSource video provider: COM initialization failure");
|
throw AudioOpenError("COM initialization failure");
|
||||||
#endif
|
#endif
|
||||||
FFMS_Init(0);
|
FFMS_Init(0);
|
||||||
|
|
||||||
|
@ -72,10 +72,6 @@ FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename) {
|
||||||
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
|
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
|
||||||
ErrInfo.ErrorType = FFMS_ERROR_SUCCESS;
|
ErrInfo.ErrorType = FFMS_ERROR_SUCCESS;
|
||||||
ErrInfo.SubType = FFMS_ERROR_SUCCESS;
|
ErrInfo.SubType = FFMS_ERROR_SUCCESS;
|
||||||
ErrorMsg = _T("FFmpegSource audio provider: ");
|
|
||||||
|
|
||||||
AudioSource = NULL;
|
|
||||||
|
|
||||||
SetLogLevel();
|
SetLogLevel();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -86,28 +82,20 @@ FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Load audio file
|
/// @brief Load audio file
|
||||||
/// @param filename
|
/// @param filename
|
||||||
///
|
///
|
||||||
void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
||||||
// clean up
|
|
||||||
Close();
|
|
||||||
|
|
||||||
wxString FileNameShort = wxFileName(filename).GetShortPath();
|
wxString FileNameShort = wxFileName(filename).GetShortPath();
|
||||||
|
|
||||||
FFMS_Indexer *Indexer = FFMS_CreateIndexer(FileNameShort.utf8_str(), &ErrInfo);
|
FFMS_Indexer *Indexer = FFMS_CreateIndexer(FileNameShort.utf8_str(), &ErrInfo);
|
||||||
if (Indexer == NULL) {
|
if (Indexer == NULL) {
|
||||||
// error messages that can possibly contain a filename use this method instead of
|
throw agi::FileNotFoundError(ErrInfo.Buffer);
|
||||||
// wxString::Format because they may contain utf8 characters
|
|
||||||
ErrorMsg.Append(_T("Failed to create indexer: ")).Append(wxString(ErrInfo.Buffer, wxConvUTF8));
|
|
||||||
throw ErrorMsg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int,wxString> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_AUDIO);
|
std::map<int,wxString> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_AUDIO);
|
||||||
if (TrackList.size() <= 0)
|
if (TrackList.size() <= 0)
|
||||||
throw _T("FFmpegSource audio provider: no audio tracks found");
|
throw AudioOpenError("no audio tracks found");
|
||||||
|
|
||||||
// initialize the track number to an invalid value so we can detect later on
|
// initialize the track number to an invalid value so we can detect later on
|
||||||
// whether the user actually had to choose a track or not
|
// whether the user actually had to choose a track or not
|
||||||
|
@ -116,7 +104,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
||||||
TrackNumber = AskForTrackSelection(TrackList, FFMS_TYPE_AUDIO);
|
TrackNumber = AskForTrackSelection(TrackList, FFMS_TYPE_AUDIO);
|
||||||
// if it's still -1 here, user pressed cancel
|
// if it's still -1 here, user pressed cancel
|
||||||
if (TrackNumber == -1)
|
if (TrackNumber == -1)
|
||||||
throw _T("FFmpegSource audio provider: audio loading cancelled by user");
|
throw agi::UserCancelException("audio loading cancelled by user");
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a name for the cache file
|
// generate a name for the cache file
|
||||||
|
@ -143,8 +131,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
||||||
if (TrackNumber < 0) {
|
if (TrackNumber < 0) {
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
Index = NULL;
|
Index = NULL;
|
||||||
ErrorMsg.Append(wxString::Format(_T("Couldn't find any audio tracks: %s"), ErrInfo.Buffer));
|
throw AudioOpenError(std::string("Couldn't find any audio tracks: ") + ErrInfo.Buffer);
|
||||||
throw ErrorMsg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// index is valid and track number is now set,
|
// index is valid and track number is now set,
|
||||||
|
@ -171,11 +158,9 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Index = DoIndexing(Indexer, CacheName, TrackMask, GetErrorHandlingMode());
|
Index = DoIndexing(Indexer, CacheName, TrackMask, GetErrorHandlingMode());
|
||||||
} catch (wxString temp) {
|
}
|
||||||
ErrorMsg.Append(temp);
|
catch (wxString const& err) {
|
||||||
throw ErrorMsg;
|
throw AudioOpenError(STD_STR(err));
|
||||||
} catch (...) {
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if tracknumber still isn't set we need to set it now
|
// if tracknumber still isn't set we need to set it now
|
||||||
|
@ -192,8 +177,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
Index = NULL;
|
Index = NULL;
|
||||||
if (!AudioSource) {
|
if (!AudioSource) {
|
||||||
ErrorMsg.Append(wxString::Format(_T("Failed to open audio track: %s"), ErrInfo.Buffer));
|
throw AudioOpenError(std::string("Failed to open audio track: %s") + ErrInfo.Buffer);
|
||||||
throw ErrorMsg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const FFMS_AudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource);
|
const FFMS_AudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource);
|
||||||
|
@ -202,7 +186,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
||||||
sample_rate = AudioInfo.SampleRate;
|
sample_rate = AudioInfo.SampleRate;
|
||||||
num_samples = AudioInfo.NumSamples;
|
num_samples = AudioInfo.NumSamples;
|
||||||
if (channels <= 0 || sample_rate <= 0 || num_samples <= 0)
|
if (channels <= 0 || sample_rate <= 0 || num_samples <= 0)
|
||||||
throw _T("FFmpegSource audio provider: sanity check failed, consult your local psychiatrist");
|
throw AudioOpenError("sanity check failed, consult your local psychiatrist");
|
||||||
|
|
||||||
// FIXME: use the actual sample format too?
|
// FIXME: use the actual sample format too?
|
||||||
// why not just bits_per_sample/8? maybe there's some oddball format with half bytes out there somewhere...
|
// why not just bits_per_sample/8? maybe there's some oddball format with half bytes out there somewhere...
|
||||||
|
@ -212,33 +196,26 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
||||||
case 24: bytes_per_sample = 3; break;
|
case 24: bytes_per_sample = 3; break;
|
||||||
case 32: bytes_per_sample = 4; break;
|
case 32: bytes_per_sample = 4; break;
|
||||||
default:
|
default:
|
||||||
throw _T("FFmpegSource audio provider: unknown or unsupported sample format");
|
throw AudioOpenError("unknown or unsupported sample format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
///
|
///
|
||||||
FFmpegSourceAudioProvider::~FFmpegSourceAudioProvider() {
|
FFmpegSourceAudioProvider::~FFmpegSourceAudioProvider() {
|
||||||
Close();
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Clean up
|
||||||
|
///
|
||||||
|
void FFmpegSourceAudioProvider::Close() {
|
||||||
|
if (AudioSource) FFMS_DestroyAudioSource(AudioSource);
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
if (COMInited)
|
if (COMInited)
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Clean up
|
|
||||||
///
|
|
||||||
void FFmpegSourceAudioProvider::Close() {
|
|
||||||
FFMS_DestroyAudioSource(AudioSource);
|
|
||||||
AudioSource = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get audio
|
/// @brief Get audio
|
||||||
/// @param Buf
|
/// @param Buf
|
||||||
/// @param Start
|
/// @param Start
|
||||||
|
@ -246,12 +223,7 @@ void FFmpegSourceAudioProvider::Close() {
|
||||||
///
|
///
|
||||||
void FFmpegSourceAudioProvider::GetAudio(void *Buf, int64_t Start, int64_t Count) {
|
void FFmpegSourceAudioProvider::GetAudio(void *Buf, int64_t Start, int64_t Count) {
|
||||||
if (FFMS_GetAudio(AudioSource, Buf, Start, Count, &ErrInfo)) {
|
if (FFMS_GetAudio(AudioSource, Buf, Start, Count, &ErrInfo)) {
|
||||||
ErrorMsg.Append(wxString::Format(_T("Failed to get audio samples: %s"), ErrInfo.Buffer));
|
throw AudioDecodeError(std::string("Failed to get audio samples: ") + ErrInfo.Buffer);
|
||||||
throw ErrorMsg;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* WITH_FFMPEGSOURCE */
|
#endif /* WITH_FFMPEGSOURCE */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
|
|
||||||
|
|
||||||
/// @class FFmpegSourceAudioProvider
|
/// @class FFmpegSourceAudioProvider
|
||||||
/// @brief Implents audio loading with the FFMS library.
|
/// @brief Implements audio loading with the FFMS library.
|
||||||
class FFmpegSourceAudioProvider : public AudioProvider, FFmpegSourceProvider {
|
class FFmpegSourceAudioProvider : public AudioProvider, FFmpegSourceProvider {
|
||||||
private:
|
private:
|
||||||
FFMS_AudioSource *AudioSource; /// audio source object
|
FFMS_AudioSource *AudioSource; /// audio source object
|
||||||
|
@ -48,7 +48,6 @@ private:
|
||||||
|
|
||||||
char FFMSErrMsg[1024]; /// FFMS error message
|
char FFMSErrMsg[1024]; /// FFMS error message
|
||||||
FFMS_ErrorInfo ErrInfo; /// FFMS error codes/messages
|
FFMS_ErrorInfo ErrInfo; /// FFMS error codes/messages
|
||||||
wxString ErrorMsg; /// wx-ified error message
|
|
||||||
|
|
||||||
void Close();
|
void Close();
|
||||||
void LoadAudio(wxString filename);
|
void LoadAudio(wxString filename);
|
||||||
|
@ -61,6 +60,7 @@ public:
|
||||||
/// @return Returns true.
|
/// @return Returns true.
|
||||||
/// FFMS always delivers native endian samples.
|
/// FFMS always delivers native endian samples.
|
||||||
bool AreSamplesNativeEndian() const { return true; }
|
bool AreSamplesNativeEndian() const { return true; }
|
||||||
|
bool NeedsCache() const { return true; }
|
||||||
|
|
||||||
virtual void GetAudio(void *buf, int64_t start, int64_t count);
|
virtual void GetAudio(void *buf, int64_t start, int64_t count);
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,14 +34,9 @@
|
||||||
/// @ingroup audio_input
|
/// @ingroup audio_input
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <wx/file.h>
|
|
||||||
#include <wx/filefn.h>
|
#include <wx/filefn.h>
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -54,11 +49,11 @@
|
||||||
#include "standard_paths.h"
|
#include "standard_paths.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param source
|
/// @param source
|
||||||
///
|
///
|
||||||
HDAudioProvider::HDAudioProvider(AudioProvider *source) {
|
HDAudioProvider::HDAudioProvider(AudioProvider *src) {
|
||||||
|
std::auto_ptr<AudioProvider> source(src);
|
||||||
// Copy parameters
|
// Copy parameters
|
||||||
bytes_per_sample = source->GetBytesPerSample();
|
bytes_per_sample = source->GetBytesPerSample();
|
||||||
num_samples = source->GetNumSamples();
|
num_samples = source->GetNumSamples();
|
||||||
|
@ -71,7 +66,7 @@ HDAudioProvider::HDAudioProvider(AudioProvider *source) {
|
||||||
wxLongLong freespace;
|
wxLongLong freespace;
|
||||||
if (wxGetDiskSpace(DiskCachePath(), NULL, &freespace)) {
|
if (wxGetDiskSpace(DiskCachePath(), NULL, &freespace)) {
|
||||||
if (num_samples * channels * bytes_per_sample > freespace) {
|
if (num_samples * channels * bytes_per_sample > freespace) {
|
||||||
throw wxString(_T("Not enough free disk space in "))+DiskCachePath()+wxString(_T(" to cache the audio"));
|
throw AudioOpenError("Not enough free disk space in " + STD_STR(DiskCachePath()) + " to cache the audio");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +74,7 @@ HDAudioProvider::HDAudioProvider(AudioProvider *source) {
|
||||||
diskCacheFilename = DiskCacheName();
|
diskCacheFilename = DiskCacheName();
|
||||||
file_cache.Create(diskCacheFilename,true,wxS_DEFAULT);
|
file_cache.Create(diskCacheFilename,true,wxS_DEFAULT);
|
||||||
file_cache.Open(diskCacheFilename,wxFile::read_write);
|
file_cache.Open(diskCacheFilename,wxFile::read_write);
|
||||||
if (!file_cache.IsOpened()) throw _T("Unable to write to audio disk cache.");
|
if (!file_cache.IsOpened()) throw AudioOpenError("Unable to write to audio disk cache.");
|
||||||
|
|
||||||
// Start progress
|
// Start progress
|
||||||
volatile bool canceled = false;
|
volatile bool canceled = false;
|
||||||
|
@ -102,12 +97,10 @@ HDAudioProvider::HDAudioProvider(AudioProvider *source) {
|
||||||
if (canceled) {
|
if (canceled) {
|
||||||
file_cache.Close();
|
file_cache.Close();
|
||||||
delete[] data;
|
delete[] data;
|
||||||
throw wxString(_T("Audio loading cancelled by user"));
|
throw agi::UserCancelException("Audio loading cancelled by user");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
///
|
///
|
||||||
HDAudioProvider::~HDAudioProvider() {
|
HDAudioProvider::~HDAudioProvider() {
|
||||||
|
@ -116,8 +109,6 @@ HDAudioProvider::~HDAudioProvider() {
|
||||||
delete[] data;
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get audio
|
/// @brief Get audio
|
||||||
/// @param buf
|
/// @param buf
|
||||||
/// @param start
|
/// @param start
|
||||||
|
@ -152,8 +143,6 @@ void HDAudioProvider::GetAudio(void *buf, int64_t start, int64_t count) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get disk cache path
|
/// @brief Get disk cache path
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -166,8 +155,6 @@ wxString HDAudioProvider::DiskCachePath() {
|
||||||
return DecodeRelativePath(path,StandardPaths::DecodePath(_T("?user/")));
|
return DecodeRelativePath(path,StandardPaths::DecodePath(_T("?user/")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get disk cache filename
|
/// @brief Get disk cache filename
|
||||||
///
|
///
|
||||||
wxString HDAudioProvider::DiskCacheName() {
|
wxString HDAudioProvider::DiskCacheName() {
|
||||||
|
@ -180,17 +167,6 @@ wxString HDAudioProvider::DiskCacheName() {
|
||||||
// File exists?
|
// File exists?
|
||||||
wxString curStringTry = DiskCachePath() + wxString::Format(pattern.c_str(),i);
|
wxString curStringTry = DiskCachePath() + wxString::Format(pattern.c_str(),i);
|
||||||
if (!wxFile::Exists(curStringTry)) return curStringTry;
|
if (!wxFile::Exists(curStringTry)) return curStringTry;
|
||||||
|
|
||||||
// Exists, see if it can be opened (disabled because wx doesn't seem to lock the files...)
|
|
||||||
if (false) {
|
|
||||||
wxFile test(curStringTry,wxFile::write);
|
|
||||||
if (test.IsOpened()) {
|
|
||||||
test.Close();
|
|
||||||
return curStringTry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return _T("");
|
return L"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,6 @@
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class HDAudioProvider : public AudioProvider {
|
class HDAudioProvider : public AudioProvider {
|
||||||
private:
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
wxMutex diskmutex;
|
wxMutex diskmutex;
|
||||||
|
|
||||||
|
@ -71,9 +69,6 @@ public:
|
||||||
HDAudioProvider(AudioProvider *source);
|
HDAudioProvider(AudioProvider *source);
|
||||||
~HDAudioProvider();
|
~HDAudioProvider();
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
///
|
|
||||||
bool AreSamplesNativeEndian() const { return samples_native_endian; }
|
bool AreSamplesNativeEndian() const { return samples_native_endian; }
|
||||||
|
|
||||||
void GetAudio(void *buf, int64_t start, int64_t count);
|
void GetAudio(void *buf, int64_t start, int64_t count);
|
||||||
|
|
|
@ -64,7 +64,6 @@
|
||||||
PCMAudioProvider::PCMAudioProvider(const wxString &filename)
|
PCMAudioProvider::PCMAudioProvider(const wxString &filename)
|
||||||
{
|
{
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
|
|
||||||
file_handle = CreateFile(
|
file_handle = CreateFile(
|
||||||
filename.c_str(),
|
filename.c_str(),
|
||||||
FILE_READ_DATA,
|
FILE_READ_DATA,
|
||||||
|
@ -75,14 +74,13 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename)
|
||||||
0);
|
0);
|
||||||
|
|
||||||
if (file_handle == INVALID_HANDLE_VALUE) {
|
if (file_handle == INVALID_HANDLE_VALUE) {
|
||||||
wxLogWarning(_T("PCM audio provider: Could not open audio file for reading (%d)"), GetLastError());
|
throw agi::FileNotFoundError(filename);
|
||||||
throw "PCM audio provider: Could not open audio file for reading";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LARGE_INTEGER li_file_size = {0};
|
LARGE_INTEGER li_file_size = {0};
|
||||||
if (!GetFileSizeEx(file_handle, &li_file_size)) {
|
if (!GetFileSizeEx(file_handle, &li_file_size)) {
|
||||||
CloseHandle(file_handle);
|
CloseHandle(file_handle);
|
||||||
throw "PCM audio provider: Failed getting file size";
|
throw AudioOpenError("Failed getting file size");
|
||||||
}
|
}
|
||||||
file_size = li_file_size.QuadPart;
|
file_size = li_file_size.QuadPart;
|
||||||
|
|
||||||
|
@ -95,7 +93,7 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename)
|
||||||
|
|
||||||
if (file_mapping == 0) {
|
if (file_mapping == 0) {
|
||||||
CloseHandle(file_handle);
|
CloseHandle(file_handle);
|
||||||
throw "PCM audio provider: Failed creating file mapping";
|
throw AudioOpenError("Failed creating file mapping");
|
||||||
}
|
}
|
||||||
|
|
||||||
current_mapping = 0;
|
current_mapping = 0;
|
||||||
|
@ -105,50 +103,41 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename)
|
||||||
file_handle = open(filename.mb_str(*wxConvFileName), O_RDONLY);
|
file_handle = open(filename.mb_str(*wxConvFileName), O_RDONLY);
|
||||||
|
|
||||||
if (file_handle == -1) {
|
if (file_handle == -1) {
|
||||||
throw "PCM audio provider: Could not open audio file for reading";
|
throw agi::FileNotFoundError(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct stat filestats;
|
struct stat filestats;
|
||||||
memset(&filestats, 0, sizeof(filestats));
|
memset(&filestats, 0, sizeof(filestats));
|
||||||
if (fstat(file_handle, &filestats)) {
|
if (fstat(file_handle, &filestats)) {
|
||||||
close(file_handle);
|
close(file_handle);
|
||||||
throw "PCM audio provider: Could not stat file to get size";
|
throw AudioOpenError("Could not stat file to get size");
|
||||||
}
|
}
|
||||||
file_size = filestats.st_size;
|
file_size = filestats.st_size;
|
||||||
|
|
||||||
current_mapping = 0;
|
current_mapping = 0;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
///
|
///
|
||||||
PCMAudioProvider::~PCMAudioProvider()
|
PCMAudioProvider::~PCMAudioProvider()
|
||||||
{
|
{
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
|
|
||||||
if (current_mapping) {
|
if (current_mapping) {
|
||||||
UnmapViewOfFile(current_mapping);
|
UnmapViewOfFile(current_mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(file_mapping);
|
CloseHandle(file_mapping);
|
||||||
CloseHandle(file_handle);
|
CloseHandle(file_handle);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if (current_mapping) {
|
if (current_mapping) {
|
||||||
munmap(current_mapping, mapping_length);
|
munmap(current_mapping, mapping_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(file_handle);
|
close(file_handle);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param range_start
|
/// @param range_start
|
||||||
/// @param range_length
|
/// @param range_length
|
||||||
|
@ -157,14 +146,12 @@ PCMAudioProvider::~PCMAudioProvider()
|
||||||
char * PCMAudioProvider::EnsureRangeAccessible(int64_t range_start, int64_t range_length)
|
char * PCMAudioProvider::EnsureRangeAccessible(int64_t range_start, int64_t range_length)
|
||||||
{
|
{
|
||||||
if (range_start + range_length > file_size) {
|
if (range_start + range_length > file_size) {
|
||||||
throw "PCM audio provider: Attempted to map beyond end of file";
|
throw AudioDecodeError("Attempted to map beyond end of file");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether the requested range is already visible
|
// Check whether the requested range is already visible
|
||||||
if (!current_mapping || range_start < mapping_start || range_start+range_length > mapping_start+(int64_t)mapping_length) {
|
if (!current_mapping || range_start < mapping_start || range_start+range_length > mapping_start+(int64_t)mapping_length) {
|
||||||
|
|
||||||
// It's not visible, change the current mapping
|
// It's not visible, change the current mapping
|
||||||
|
|
||||||
if (current_mapping) {
|
if (current_mapping) {
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
UnmapViewOfFile(current_mapping);
|
UnmapViewOfFile(current_mapping);
|
||||||
|
@ -187,9 +174,8 @@ char * PCMAudioProvider::EnsureRangeAccessible(int64_t range_start, int64_t rang
|
||||||
// Make sure to always make a mapping at least as large as the requested range
|
// Make sure to always make a mapping at least as large as the requested range
|
||||||
if ((int64_t)mapping_length < range_length) {
|
if ((int64_t)mapping_length < range_length) {
|
||||||
if (range_length > (int64_t)(~(size_t)0))
|
if (range_length > (int64_t)(~(size_t)0))
|
||||||
throw "PCM audio provider: Requested range larger than max size_t, cannot create view of file";
|
throw AudioDecodeError("Requested range larger than max size_t, cannot create view of file");
|
||||||
else
|
mapping_length = range_length;
|
||||||
mapping_length = range_length;
|
|
||||||
}
|
}
|
||||||
// But also make sure we don't try to make a mapping larger than the file
|
// But also make sure we don't try to make a mapping larger than the file
|
||||||
if (mapping_start + (int64_t)mapping_length > file_size)
|
if (mapping_start + (int64_t)mapping_length > file_size)
|
||||||
|
@ -211,9 +197,8 @@ char * PCMAudioProvider::EnsureRangeAccessible(int64_t range_start, int64_t rang
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!current_mapping) {
|
if (!current_mapping) {
|
||||||
throw "PCM audio provider: Failed mapping a view of the file";
|
throw AudioDecodeError("Failed mapping a view of the file");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(current_mapping);
|
assert(current_mapping);
|
||||||
|
@ -226,8 +211,6 @@ char * PCMAudioProvider::EnsureRangeAccessible(int64_t range_start, int64_t rang
|
||||||
return ((char*)current_mapping) + rel_ofs;
|
return ((char*)current_mapping) + rel_ofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param buf
|
/// @param buf
|
||||||
/// @param start
|
/// @param start
|
||||||
|
@ -256,9 +239,7 @@ void PCMAudioProvider::GetAudio(void *buf, int64_t start, int64_t count)
|
||||||
buf = (char*)buf + samples_can_do * bytes_per_sample * channels;
|
buf = (char*)buf + samples_can_do * bytes_per_sample * channels;
|
||||||
start += samples_can_do;
|
start += samples_can_do;
|
||||||
count -= samples_can_do;
|
count -= samples_can_do;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,26 +254,17 @@ void PCMAudioProvider::GetAudio(void *buf, int64_t start, int64_t count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// RIFF WAV PCM provider
|
|
||||||
// Overview of RIFF WAV: <http://www.sonicspot.com/guide/wavefiles.html>
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class RiffWavPCMAudioProvider
|
/// @class RiffWavPCMAudioProvider
|
||||||
/// @brief DOCME
|
/// @brief RIFF WAV PCM provider
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// Overview of RIFF WAV: <http://www.sonicspot.com/guide/wavefiles.html>
|
||||||
class RiffWavPCMAudioProvider : public PCMAudioProvider {
|
class RiffWavPCMAudioProvider : public PCMAudioProvider {
|
||||||
private:
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
struct ChunkHeader {
|
struct ChunkHeader {
|
||||||
|
/// Always "RIFF"
|
||||||
/// DOCME
|
|
||||||
char type[4];
|
char type[4];
|
||||||
|
/// File size minus sizeof(ChunkHeader) (i.e. 8)
|
||||||
/// DOCME
|
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -302,29 +274,31 @@ private:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
ChunkHeader ch;
|
ChunkHeader ch;
|
||||||
|
|
||||||
/// DOCME
|
/// Always "WAVE"
|
||||||
char format[4];
|
char format[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
struct fmtChunk {
|
struct fmtChunk {
|
||||||
|
|
||||||
/// DOCME
|
/// compression format used
|
||||||
uint16_t compression; // compression format used -- 0x0001 = PCM
|
/// We support only PCM (0x1)
|
||||||
|
uint16_t compression;
|
||||||
|
|
||||||
/// DOCME
|
/// Number of channels
|
||||||
uint16_t channels;
|
uint16_t channels;
|
||||||
|
|
||||||
/// DOCME
|
/// Samples per second
|
||||||
uint32_t samplerate;
|
uint32_t samplerate;
|
||||||
|
|
||||||
/// DOCME
|
/// Bytes per second
|
||||||
uint32_t avg_bytes_sec; // can't always be trusted
|
/// can't always be trusted
|
||||||
|
uint32_t avg_bytes_sec;
|
||||||
|
|
||||||
/// DOCME
|
/// Bytes per sample
|
||||||
uint16_t block_align;
|
uint16_t block_align;
|
||||||
|
|
||||||
/// DOCME
|
/// Bits per sample that are actually used; rest should be ignored
|
||||||
uint16_t significant_bits_sample;
|
uint16_t significant_bits_sample;
|
||||||
// Here was supposed to be some more fields but we don't need them
|
// Here was supposed to be some more fields but we don't need them
|
||||||
// and just skipping by the size of the struct wouldn't be safe
|
// and just skipping by the size of the struct wouldn't be safe
|
||||||
|
@ -359,16 +333,14 @@ public:
|
||||||
filename = _filename;
|
filename = _filename;
|
||||||
|
|
||||||
// Read header
|
// Read header
|
||||||
// This should throw an exception if the mapping fails
|
|
||||||
void *filestart = EnsureRangeAccessible(0, sizeof(RIFFChunk));
|
void *filestart = EnsureRangeAccessible(0, sizeof(RIFFChunk));
|
||||||
assert(filestart);
|
|
||||||
RIFFChunk &header = *(RIFFChunk*)filestart;
|
RIFFChunk &header = *(RIFFChunk*)filestart;
|
||||||
|
|
||||||
// Check magic values
|
// Check magic values
|
||||||
if (!CheckFourcc(header.ch.type, "RIFF"))
|
if (!CheckFourcc(header.ch.type, "RIFF"))
|
||||||
throw "RIFF PCM WAV audio provider: File is not a RIFF file";
|
throw AudioOpenError("File is not a RIFF file");
|
||||||
if (!CheckFourcc(header.format, "WAVE"))
|
if (!CheckFourcc(header.format, "WAVE"))
|
||||||
throw "RIFF PCM WAV audio provider: File is not a RIFF WAV file";
|
throw AudioOpenError("File is not a RIFF WAV file");
|
||||||
|
|
||||||
// Count how much more data we can have in the entire file
|
// Count how much more data we can have in the entire file
|
||||||
// The first 4 bytes are already eaten by the header.format field
|
// The first 4 bytes are already eaten by the header.format field
|
||||||
|
@ -391,12 +363,13 @@ public:
|
||||||
filepos += sizeof(ch);
|
filepos += sizeof(ch);
|
||||||
|
|
||||||
if (CheckFourcc(ch.type, "fmt ")) {
|
if (CheckFourcc(ch.type, "fmt ")) {
|
||||||
if (got_fmt_header) throw "RIFF PCM WAV audio provider: Invalid file, multiple 'fmt ' chunks";
|
if (got_fmt_header) throw AudioOpenError("Invalid file, multiple 'fmt ' chunks");
|
||||||
got_fmt_header = true;
|
got_fmt_header = true;
|
||||||
|
|
||||||
fmtChunk &fmt = *(fmtChunk*)EnsureRangeAccessible(filepos, sizeof(fmtChunk));
|
fmtChunk &fmt = *(fmtChunk*)EnsureRangeAccessible(filepos, sizeof(fmtChunk));
|
||||||
|
|
||||||
if (Endian::LittleToMachine(fmt.compression) != 1) throw "RIFF PCM WAV audio provider: Can't use file, not PCM encoding";
|
if (Endian::LittleToMachine(fmt.compression) != 1)
|
||||||
|
throw AudioOpenError("Can't use file, not PCM encoding");
|
||||||
|
|
||||||
// Set stuff inherited from the AudioProvider class
|
// Set stuff inherited from the AudioProvider class
|
||||||
sample_rate = Endian::LittleToMachine(fmt.samplerate);
|
sample_rate = Endian::LittleToMachine(fmt.samplerate);
|
||||||
|
@ -408,7 +381,7 @@ public:
|
||||||
// This won't pick up 'data' chunks inside 'wavl' chunks
|
// This won't pick up 'data' chunks inside 'wavl' chunks
|
||||||
// since the 'wavl' chunks wrap those.
|
// since the 'wavl' chunks wrap those.
|
||||||
|
|
||||||
if (!got_fmt_header) throw "RIFF PCM WAV audio provider: Found 'data' chunk before 'fmt ' chunk, file is invalid.";
|
if (!got_fmt_header) throw AudioOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.");
|
||||||
|
|
||||||
int64_t samples = Endian::LittleToMachine(ch.size) / bytes_per_sample;
|
int64_t samples = Endian::LittleToMachine(ch.size) / bytes_per_sample;
|
||||||
int64_t frames = samples / channels;
|
int64_t frames = samples / channels;
|
||||||
|
@ -431,8 +404,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -446,12 +417,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Sony Wave64 audio provider
|
|
||||||
// Specs obtained at: <http://www.vcs.de/fileadmin/user_upload/MBS/PDF/Whitepaper/Informations_about_Sony_Wave64.pdf>
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
static const uint8_t w64GuidRIFF[16] = {
|
static const uint8_t w64GuidRIFF[16] = {
|
||||||
// {66666972-912E-11CF-A5D6-28DB04C10000}
|
// {66666972-912E-11CF-A5D6-28DB04C10000}
|
||||||
|
@ -482,43 +447,25 @@ static const uint8_t w64Guiddata[16] = {
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class Wave64AudioProvider
|
/// @class Wave64AudioProvider
|
||||||
/// @brief DOCME
|
/// @brief Sony Wave64 audio provider
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// http://www.vcs.de/fileadmin/user_upload/MBS/PDF/Whitepaper/Informations_about_Sony_Wave64.pdf
|
||||||
class Wave64AudioProvider : public PCMAudioProvider {
|
class Wave64AudioProvider : public PCMAudioProvider {
|
||||||
private:
|
|
||||||
// Here's some copy-paste from the FFmpegSource2 code
|
// Here's some copy-paste from the FFmpegSource2 code
|
||||||
|
|
||||||
|
/// http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx
|
||||||
/// DOCME
|
|
||||||
struct WaveFormatEx {
|
struct WaveFormatEx {
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
uint16_t wFormatTag;
|
uint16_t wFormatTag;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
uint16_t nChannels;
|
uint16_t nChannels;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
uint32_t nSamplesPerSec;
|
uint32_t nSamplesPerSec;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
uint32_t nAvgBytesPerSec;
|
uint32_t nAvgBytesPerSec;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
uint16_t nBlockAlign;
|
uint16_t nBlockAlign;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
uint16_t wBitsPerSample;
|
uint16_t wBitsPerSample;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
uint16_t cbSize;
|
uint16_t cbSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
struct RiffChunk {
|
struct RiffChunk {
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
uint8_t riff_guid[16];
|
uint8_t riff_guid[16];
|
||||||
|
|
||||||
|
@ -532,7 +479,6 @@ private:
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
struct FormatChunk {
|
struct FormatChunk {
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
uint8_t chunk_guid[16];
|
uint8_t chunk_guid[16];
|
||||||
|
|
||||||
|
@ -549,7 +495,6 @@ private:
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
struct DataChunk {
|
struct DataChunk {
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
uint8_t chunk_guid[16];
|
uint8_t chunk_guid[16];
|
||||||
|
|
||||||
|
@ -557,7 +502,6 @@ private:
|
||||||
uint64_t chunk_size;
|
uint64_t chunk_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param guid1
|
/// @param guid1
|
||||||
/// @param guid2
|
/// @param guid2
|
||||||
|
@ -581,7 +525,7 @@ public:
|
||||||
int64_t smallest_possible_file = sizeof(RiffChunk) + sizeof(FormatChunk) + sizeof(DataChunk);
|
int64_t smallest_possible_file = sizeof(RiffChunk) + sizeof(FormatChunk) + sizeof(DataChunk);
|
||||||
|
|
||||||
if (file_size < smallest_possible_file)
|
if (file_size < smallest_possible_file)
|
||||||
throw "Wave64 audio provider: File is too small to be a Wave64 file";
|
throw AudioOpenError("File is too small to be a Wave64 file");
|
||||||
|
|
||||||
// Read header
|
// Read header
|
||||||
// This should throw an exception if the mapping fails
|
// This should throw an exception if the mapping fails
|
||||||
|
@ -591,9 +535,9 @@ public:
|
||||||
|
|
||||||
// Check magic values
|
// Check magic values
|
||||||
if (!CheckGuid(header.riff_guid, w64GuidRIFF))
|
if (!CheckGuid(header.riff_guid, w64GuidRIFF))
|
||||||
throw "Wave64 audio provider: File is not a Wave64 RIFF file";
|
throw AudioOpenError("File is not a Wave64 RIFF file");
|
||||||
if (!CheckGuid(header.format_guid, w64GuidWAVE))
|
if (!CheckGuid(header.format_guid, w64GuidWAVE))
|
||||||
throw "Wave64 audio provider: File is not a Wave64 WAVE file";
|
throw AudioOpenError("File is not a Wave64 WAVE file");
|
||||||
|
|
||||||
// Count how much more data we can have in the entire file
|
// Count how much more data we can have in the entire file
|
||||||
uint64_t data_left = Endian::LittleToMachine(header.file_size) - sizeof(RiffChunk);
|
uint64_t data_left = Endian::LittleToMachine(header.file_size) - sizeof(RiffChunk);
|
||||||
|
@ -613,25 +557,24 @@ public:
|
||||||
|
|
||||||
if (CheckGuid(chunk_guid, w64Guidfmt)) {
|
if (CheckGuid(chunk_guid, w64Guidfmt)) {
|
||||||
if (got_fmt_header)
|
if (got_fmt_header)
|
||||||
throw "Wave64 audio provider: Bad file, found more than one 'fmt' chunk";
|
throw AudioOpenError("Bad file, found more than one 'fmt' chunk");
|
||||||
|
|
||||||
FormatChunk &fmt = *(FormatChunk*)EnsureRangeAccessible(filepos, sizeof(FormatChunk));
|
FormatChunk &fmt = *(FormatChunk*)EnsureRangeAccessible(filepos, sizeof(FormatChunk));
|
||||||
got_fmt_header = true;
|
got_fmt_header = true;
|
||||||
|
|
||||||
if (Endian::LittleToMachine(fmt.format.wFormatTag) == 3)
|
if (Endian::LittleToMachine(fmt.format.wFormatTag) == 3)
|
||||||
throw "Wave64 audio provider: File is IEEE 32 bit float format which isn't supported. Bug the developers if this matters.";
|
throw AudioOpenError("File is IEEE 32 bit float format which isn't supported. Bug the developers if this matters.");
|
||||||
if (Endian::LittleToMachine(fmt.format.wFormatTag) != 1)
|
if (Endian::LittleToMachine(fmt.format.wFormatTag) != 1)
|
||||||
throw "Wave64 audio provider: Can't use file, not PCM encoding";
|
throw AudioOpenError("Can't use file, not PCM encoding");
|
||||||
|
|
||||||
// Set stuff inherited from the AudioProvider class
|
// Set stuff inherited from the AudioProvider class
|
||||||
sample_rate = Endian::LittleToMachine(fmt.format.nSamplesPerSec);
|
sample_rate = Endian::LittleToMachine(fmt.format.nSamplesPerSec);
|
||||||
channels = Endian::LittleToMachine(fmt.format.nChannels);
|
channels = Endian::LittleToMachine(fmt.format.nChannels);
|
||||||
bytes_per_sample = (Endian::LittleToMachine(fmt.format.wBitsPerSample) + 7) / 8; // round up to nearest whole byte
|
bytes_per_sample = (Endian::LittleToMachine(fmt.format.wBitsPerSample) + 7) / 8; // round up to nearest whole byte
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (CheckGuid(chunk_guid, w64Guiddata)) {
|
else if (CheckGuid(chunk_guid, w64Guiddata)) {
|
||||||
if (!got_fmt_header)
|
if (!got_fmt_header)
|
||||||
throw "Wave64 audio provider: Found 'data' chunk before 'fmt ' chunk, file is invalid.";
|
throw AudioOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.");
|
||||||
|
|
||||||
int64_t samples = chunk_size / bytes_per_sample;
|
int64_t samples = chunk_size / bytes_per_sample;
|
||||||
int64_t frames = samples / channels;
|
int64_t frames = samples / channels;
|
||||||
|
@ -652,8 +595,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -667,38 +608,23 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param filename
|
/// @param filename
|
||||||
///
|
///
|
||||||
AudioProvider *CreatePCMAudioProvider(const wxString &filename)
|
AudioProvider *CreatePCMAudioProvider(const wxString &filename)
|
||||||
{
|
{
|
||||||
AudioProvider *provider = 0;
|
std::string msg;
|
||||||
|
|
||||||
// Try Microsoft/IBM RIFF WAV
|
|
||||||
try {
|
try {
|
||||||
provider = new RiffWavPCMAudioProvider(filename);
|
return new RiffWavPCMAudioProvider(filename);
|
||||||
// don't bother trying with anything else if this works
|
|
||||||
return provider;
|
|
||||||
}
|
}
|
||||||
catch (const char *msg) {
|
catch (AudioOpenError const& err) {
|
||||||
LOG_E("audio/provider/pcm") << "Creating PCM WAV reader failed with message: '" << msg << "' Trying other providers";
|
msg = "RIFF PCM WAV audio provider: " + err.GetMessage();
|
||||||
provider = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try Sony Wave64
|
|
||||||
try {
|
try {
|
||||||
provider = new Wave64AudioProvider(filename);
|
return new Wave64AudioProvider(filename);
|
||||||
return provider;
|
|
||||||
}
|
}
|
||||||
catch (const char *msg) {
|
catch (AudioOpenError const& err) {
|
||||||
LOG_E("audio/provider/pcm") << "Creating Wave64 reader failed with message: '" << msg << "' Trying other providers";
|
msg += "\nWave64 audio provider: " + err.GetMessage();
|
||||||
provider = 0;
|
throw AudioOpenError(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no providers could be created
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,6 @@
|
||||||
/// @ingroup audio_input
|
/// @ingroup audio_input
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "audio_provider_ram.h"
|
#include "audio_provider_ram.h"
|
||||||
|
@ -52,12 +49,11 @@
|
||||||
/// DOCME
|
/// DOCME
|
||||||
#define CacheBlockSize ((1 << CacheBits))
|
#define CacheBlockSize ((1 << CacheBits))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param source
|
/// @param source
|
||||||
///
|
///
|
||||||
RAMAudioProvider::RAMAudioProvider(AudioProvider *source) {
|
RAMAudioProvider::RAMAudioProvider(AudioProvider *src) {
|
||||||
|
std::auto_ptr<AudioProvider> source(src);
|
||||||
// Init
|
// Init
|
||||||
blockcache = NULL;
|
blockcache = NULL;
|
||||||
blockcount = 0;
|
blockcount = 0;
|
||||||
|
@ -79,7 +75,7 @@ RAMAudioProvider::RAMAudioProvider(AudioProvider *source) {
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
Clear();
|
Clear();
|
||||||
throw wxString(_T("Couldn't open audio, not enough ram available."));
|
throw AudioOpenError("Couldn't open audio, not enough ram available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy parameters
|
// Copy parameters
|
||||||
|
@ -98,7 +94,6 @@ RAMAudioProvider::RAMAudioProvider(AudioProvider *source) {
|
||||||
// Read cache
|
// Read cache
|
||||||
int readsize = CacheBlockSize / source->GetBytesPerSample();
|
int readsize = CacheBlockSize / source->GetBytesPerSample();
|
||||||
for (int i=0;i<blockcount && !canceled; i++) {
|
for (int i=0;i<blockcount && !canceled; i++) {
|
||||||
//tempclip->GetAudio((char*)blockcache[i],i*readsize, i == blockcount-1 ? (num_samples - i*readsize) : readsize,env);
|
|
||||||
source->GetAudio((char*)blockcache[i],i*readsize, i == blockcount-1 ? (source->GetNumSamples() - i*readsize) : readsize);
|
source->GetAudio((char*)blockcache[i],i*readsize, i == blockcount-1 ? (source->GetNumSamples() - i*readsize) : readsize);
|
||||||
progress->SetProgress(i,blockcount-1);
|
progress->SetProgress(i,blockcount-1);
|
||||||
}
|
}
|
||||||
|
@ -107,20 +102,16 @@ RAMAudioProvider::RAMAudioProvider(AudioProvider *source) {
|
||||||
progress->Destroy();
|
progress->Destroy();
|
||||||
if (canceled) {
|
if (canceled) {
|
||||||
Clear();
|
Clear();
|
||||||
throw wxString(_T("Audio loading cancelled by user"));
|
throw agi::UserCancelException("Audio loading cancelled by user");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
///
|
///
|
||||||
RAMAudioProvider::~RAMAudioProvider() {
|
RAMAudioProvider::~RAMAudioProvider() {
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Clear
|
/// @brief Clear
|
||||||
///
|
///
|
||||||
void RAMAudioProvider::Clear() {
|
void RAMAudioProvider::Clear() {
|
||||||
|
@ -135,8 +126,6 @@ void RAMAudioProvider::Clear() {
|
||||||
blockcount = 0;
|
blockcount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get audio
|
/// @brief Get audio
|
||||||
/// @param buf
|
/// @param buf
|
||||||
/// @param start
|
/// @param start
|
||||||
|
@ -185,5 +174,3 @@ void RAMAudioProvider::GetAudio(void *buf, int64_t start, int64_t count) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -260,7 +260,7 @@ public:
|
||||||
// Start sample number of the next line calculated
|
// Start sample number of the next line calculated
|
||||||
// line_length is half of the number of samples used to calculate a line, since half of the output from
|
// line_length is half of the number of samples used to calculate a line, since half of the output from
|
||||||
// a Fourier transform of real data is redundant, and not interesting for the purpose of creating
|
// a Fourier transform of real data is redundant, and not interesting for the purpose of creating
|
||||||
// a frequenmcy/power spectrum.
|
// a frequency/power spectrum.
|
||||||
int64_t sample = start * line_length*2 + overlap*overlap_offset;
|
int64_t sample = start * line_length*2 + overlap*overlap_offset;
|
||||||
|
|
||||||
long len = length;
|
long len = length;
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
/// @ingroup scripting
|
/// @ingroup scripting
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef WITH_AUTOMATION
|
#ifdef WITH_AUTOMATION
|
||||||
|
@ -47,15 +46,11 @@
|
||||||
|
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
#include <wx/dcmemory.h>
|
#include <wx/dcmemory.h>
|
||||||
#include <wx/dialog.h>
|
|
||||||
#include <wx/dir.h>
|
#include <wx/dir.h>
|
||||||
#include <wx/filefn.h>
|
#include <wx/filefn.h>
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
#include <wx/gauge.h>
|
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
#include <wx/msgdlg.h>
|
#include <wx/msgdlg.h>
|
||||||
#include <wx/sizer.h>
|
|
||||||
#include <wx/stattext.h>
|
|
||||||
#include <wx/thread.h>
|
#include <wx/thread.h>
|
||||||
#include <wx/tokenzr.h>
|
#include <wx/tokenzr.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -73,12 +68,8 @@
|
||||||
#include "standard_paths.h"
|
#include "standard_paths.h"
|
||||||
#include "string_codec.h"
|
#include "string_codec.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
namespace Automation4 {
|
namespace Automation4 {
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param style
|
/// @param style
|
||||||
/// @param text
|
/// @param text
|
||||||
|
|
|
@ -34,9 +34,6 @@
|
||||||
/// @ingroup scripting
|
/// @ingroup scripting
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <wx/event.h>
|
#include <wx/event.h>
|
||||||
#include <wx/thread.h>
|
#include <wx/thread.h>
|
||||||
|
@ -47,7 +44,6 @@
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
#include "../../contrib/lua51/src/lua.h"
|
#include "../../contrib/lua51/src/lua.h"
|
||||||
#include "../../contrib/lua51/src/lauxlib.h"
|
|
||||||
#else
|
#else
|
||||||
#include <lua.hpp>
|
#include <lua.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
@ -55,11 +51,8 @@
|
||||||
class wxWindow;
|
class wxWindow;
|
||||||
namespace agi { namespace vfr { class Framerate; } }
|
namespace agi { namespace vfr { class Framerate; } }
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
namespace Automation4 {
|
namespace Automation4 {
|
||||||
|
|
||||||
|
|
||||||
/// @class LuaAssFile
|
/// @class LuaAssFile
|
||||||
/// @brief Object wrapping an AssFile object for modification through Lua
|
/// @brief Object wrapping an AssFile object for modification through Lua
|
||||||
class LuaAssFile {
|
class LuaAssFile {
|
||||||
|
|
|
@ -46,6 +46,7 @@ HINSTANCE AviSynthWrapper::hLib = NULL;
|
||||||
IScriptEnvironment *AviSynthWrapper::env = NULL;
|
IScriptEnvironment *AviSynthWrapper::env = NULL;
|
||||||
wxMutex AviSynthWrapper::AviSynthMutex;
|
wxMutex AviSynthWrapper::AviSynthMutex;
|
||||||
|
|
||||||
|
|
||||||
/// @brief AviSynth constructor
|
/// @brief AviSynth constructor
|
||||||
///
|
///
|
||||||
AviSynthWrapper::AviSynthWrapper() {
|
AviSynthWrapper::AviSynthWrapper() {
|
||||||
|
@ -96,3 +97,4 @@ IScriptEnvironment *AviSynthWrapper::GetEnv() {
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include <libaegisub/colour.h>
|
#include <libaegisub/colour.h>
|
||||||
|
|
||||||
#define STD_STR(x) std::string(x.utf8_str())
|
#define STD_STR(x) std::string((x).utf8_str())
|
||||||
|
|
||||||
inline wxColour lagi_wxColour(const agi::Colour &colour) { return wxColour(colour); }
|
inline wxColour lagi_wxColour(const agi::Colour &colour) { return wxColour(colour); }
|
||||||
inline wxString lagi_wxString(const std::string &str) { return wxString(str.c_str(), wxConvUTF8); }
|
inline wxString lagi_wxString(const std::string &str) { return wxString(str.c_str(), wxConvUTF8); }
|
||||||
|
|
|
@ -38,8 +38,6 @@
|
||||||
|
|
||||||
#ifdef WITH_FFMPEGSOURCE
|
#ifdef WITH_FFMPEGSOURCE
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <wx/dir.h>
|
#include <wx/dir.h>
|
||||||
|
@ -98,7 +96,8 @@ FFMS_Index *FFmpegSourceProvider::DoIndexing(FFMS_Indexer *Indexer, const wxStri
|
||||||
// set up progress dialog callback
|
// set up progress dialog callback
|
||||||
IndexingProgressDialog Progress;
|
IndexingProgressDialog Progress;
|
||||||
Progress.IndexingCanceled = false;
|
Progress.IndexingCanceled = false;
|
||||||
Progress.ProgressDialog = new DialogProgress(AegisubApp::Get()->frame, _("Indexing"), &Progress.IndexingCanceled,
|
Progress.ProgressDialog = new DialogProgress(AegisubApp::Get()->frame,
|
||||||
|
_("Indexing"), &Progress.IndexingCanceled,
|
||||||
_("Reading timecodes and frame/sample data"), 0, 1);
|
_("Reading timecodes and frame/sample data"), 0, 1);
|
||||||
Progress.ProgressDialog->Show();
|
Progress.ProgressDialog->Show();
|
||||||
Progress.ProgressDialog->SetProgress(0,1);
|
Progress.ProgressDialog->SetProgress(0,1);
|
||||||
|
@ -106,12 +105,14 @@ FFMS_Index *FFmpegSourceProvider::DoIndexing(FFMS_Indexer *Indexer, const wxStri
|
||||||
// index all audio tracks
|
// index all audio tracks
|
||||||
FFMS_Index *Index = FFMS_DoIndexing(Indexer, Trackmask, FFMS_TRACKMASK_NONE, NULL, NULL, IndexEH,
|
FFMS_Index *Index = FFMS_DoIndexing(Indexer, Trackmask, FFMS_TRACKMASK_NONE, NULL, NULL, IndexEH,
|
||||||
FFmpegSourceProvider::UpdateIndexingProgress, &Progress, &ErrInfo);
|
FFmpegSourceProvider::UpdateIndexingProgress, &Progress, &ErrInfo);
|
||||||
|
Progress.ProgressDialog->Destroy();
|
||||||
|
if (Progress.IndexingCanceled) {
|
||||||
|
throw agi::UserCancelException("indexing cancelled by user");
|
||||||
|
}
|
||||||
if (Index == NULL) {
|
if (Index == NULL) {
|
||||||
Progress.ProgressDialog->Destroy();
|
|
||||||
MsgString.Append(_T("Failed to index: ")).Append(wxString(ErrInfo.Buffer, wxConvUTF8));
|
MsgString.Append(_T("Failed to index: ")).Append(wxString(ErrInfo.Buffer, wxConvUTF8));
|
||||||
throw MsgString;
|
throw MsgString;
|
||||||
}
|
}
|
||||||
Progress.ProgressDialog->Destroy();
|
|
||||||
|
|
||||||
// write index to disk for later use
|
// write index to disk for later use
|
||||||
// ignore write errors for now
|
// ignore write errors for now
|
||||||
|
@ -125,8 +126,6 @@ FFMS_Index *FFmpegSourceProvider::DoIndexing(FFMS_Indexer *Indexer, const wxStri
|
||||||
return Index;
|
return Index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Finds all tracks of the given type and return their track numbers and respective codec names
|
/// @brief Finds all tracks of the given type and return their track numbers and respective codec names
|
||||||
/// @param Indexer The indexer object representing the source file
|
/// @param Indexer The indexer object representing the source file
|
||||||
/// @param Type The track type to look for
|
/// @param Type The track type to look for
|
||||||
|
@ -141,12 +140,9 @@ std::map<int,wxString> FFmpegSourceProvider::GetTracksOfType(FFMS_Indexer *Index
|
||||||
TrackList.insert(std::pair<int,wxString>(i, CodecName));
|
TrackList.insert(std::pair<int,wxString>(i, CodecName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TrackList;
|
return TrackList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Ask user for which track he wants to load
|
/// @brief Ask user for which track he wants to load
|
||||||
/// @param TrackList A std::map with the track numbers as keys and codec names as values
|
/// @param TrackList A std::map with the track numbers as keys and codec names as values
|
||||||
/// @param Type The track type to ask about
|
/// @param Type The track type to ask about
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
|
|
||||||
#ifdef WITH_FFMPEGSOURCE
|
#ifdef WITH_FFMPEGSOURCE
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
@ -48,15 +46,12 @@
|
||||||
#include <ffms.h>
|
#include <ffms.h>
|
||||||
|
|
||||||
#include "dialog_progress.h"
|
#include "dialog_progress.h"
|
||||||
#include "include/aegisub/aegisub.h"
|
|
||||||
|
|
||||||
|
|
||||||
/// Index all tracks
|
/// Index all tracks
|
||||||
#define FFMS_TRACKMASK_ALL -1
|
#define FFMS_TRACKMASK_ALL -1
|
||||||
/// Index no tracks
|
/// Index no tracks
|
||||||
#define FFMS_TRACKMASK_NONE 0
|
#define FFMS_TRACKMASK_NONE 0
|
||||||
|
|
||||||
|
|
||||||
/// @class FFmpegSourceProvider
|
/// @class FFmpegSourceProvider
|
||||||
/// @brief Base class for FFMS2 source providers; contains common functions etc
|
/// @brief Base class for FFMS2 source providers; contains common functions etc
|
||||||
class FFmpegSourceProvider {
|
class FFmpegSourceProvider {
|
||||||
|
@ -97,8 +92,6 @@ public:
|
||||||
virtual ~FFmpegSourceProvider() {}
|
virtual ~FFmpegSourceProvider() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @class FFmpegSourceCacheCleaner
|
/// @class FFmpegSourceCacheCleaner
|
||||||
/// @brief Implements index cache cleaning functionality for the FFMS2 providers
|
/// @brief Implements index cache cleaning functionality for the FFMS2 providers
|
||||||
class FFmpegSourceCacheCleaner : public wxThread {
|
class FFmpegSourceCacheCleaner : public wxThread {
|
||||||
|
@ -112,8 +105,5 @@ public:
|
||||||
wxThread::ExitCode Entry();
|
wxThread::ExitCode Entry();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* WITH_FFMPEGSOURCE */
|
#endif /* WITH_FFMPEGSOURCE */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -673,7 +673,7 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
bool isFile = (filename != _T(""));
|
bool isFile = !filename.empty();
|
||||||
bool isBinary = false;
|
bool isBinary = false;
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
|
@ -681,7 +681,9 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
|
||||||
// File exists?
|
// File exists?
|
||||||
if (isFile) {
|
if (isFile) {
|
||||||
wxFileName fileCheck(filename);
|
wxFileName fileCheck(filename);
|
||||||
if (!fileCheck.FileExists()) throw _T("Selected file does not exist.");
|
if (!fileCheck.FileExists()) {
|
||||||
|
throw agi::FileNotFoundError(STD_STR(filename));
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure that file isn't actually a timecode file
|
// Make sure that file isn't actually a timecode file
|
||||||
try {
|
try {
|
||||||
|
@ -697,8 +699,8 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
// if trying to load the file as timecodes fails it's fairly safe to assume that
|
// if trying to load the file as timecodes fails it's fairly
|
||||||
// it is in fact not a timecode file
|
// safe to assume that it is in fact not a timecode file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,6 +722,11 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
|
||||||
StandardPaths::SetPathValue(_T("?script"),_T(""));
|
StandardPaths::SetPathValue(_T("?script"),_T(""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (agi::FileNotFoundError const&) {
|
||||||
|
wxMessageBox(filename + L" not found.", L"Error", wxOK | wxICON_ERROR, NULL);
|
||||||
|
config::mru->Remove("Subtitle", STD_STR(filename));
|
||||||
|
return;
|
||||||
|
}
|
||||||
catch (const wchar_t *err) {
|
catch (const wchar_t *err) {
|
||||||
wxMessageBox(wxString(err), _T("Error"), wxOK | wxICON_ERROR, NULL);
|
wxMessageBox(wxString(err), _T("Error"), wxOK | wxICON_ERROR, NULL);
|
||||||
return;
|
return;
|
||||||
|
@ -773,7 +780,7 @@ bool FrameMain::SaveSubtitles(bool saveas,bool withCharset) {
|
||||||
VideoContext::Get()->Stop();
|
VideoContext::Get()->Stop();
|
||||||
wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString());
|
wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString());
|
||||||
wxFileName origPath(ass->filename);
|
wxFileName origPath(ass->filename);
|
||||||
filename = wxFileSelector(_("Save subtitles file"),path,origPath.GetName() + _T(".ass"),_T("ass"),AssFile::GetWildcardList(1),wxFD_SAVE | wxFD_OVERWRITE_PROMPT,this);
|
filename = wxFileSelector(_("Save subtitles file"),path,origPath.GetName() + _T(".ass"),_T("ass"),AssFile::GetWildcardList(1),wxFD_SAVE | wxFD_OVERWRITE_PROMPT,this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually save
|
// Actually save
|
||||||
|
|
|
@ -34,15 +34,11 @@
|
||||||
/// @ingroup main_ui
|
/// @ingroup main_ui
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#include <wx/accel.h>
|
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -51,7 +47,6 @@
|
||||||
#include "text_file_reader.h"
|
#include "text_file_reader.h"
|
||||||
#include "text_file_writer.h"
|
#include "text_file_writer.h"
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructors HotkeyType //////////////////////////////////
|
/// @brief Constructors HotkeyType //////////////////////////////////
|
||||||
///
|
///
|
||||||
HotkeyType::HotkeyType() {
|
HotkeyType::HotkeyType() {
|
||||||
|
@ -59,7 +54,6 @@ HotkeyType::HotkeyType() {
|
||||||
keycode = 0;
|
keycode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param text
|
/// @param text
|
||||||
/// @param name
|
/// @param name
|
||||||
|
@ -69,8 +63,6 @@ HotkeyType::HotkeyType(wxString text,wxString name) {
|
||||||
origName = name;
|
origName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get string of hotkey
|
/// @brief Get string of hotkey
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -88,8 +80,6 @@ wxString HotkeyType::GetText() const {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Parse text into hotkey
|
/// @brief Parse text into hotkey
|
||||||
/// @param text
|
/// @param text
|
||||||
///
|
///
|
||||||
|
@ -150,8 +140,6 @@ void HotkeyType::Parse(wxString text) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
std::map<int,wxString> HotkeyType::keyName;
|
std::map<int,wxString> HotkeyType::keyName;
|
||||||
|
|
||||||
|
@ -172,8 +160,6 @@ wxString HotkeyType::GetKeyName(int keycode) {
|
||||||
else return wxString::Format(_T("[%i]"),keycode);
|
else return wxString::Format(_T("[%i]"),keycode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Fill map
|
/// @brief Fill map
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -234,29 +220,21 @@ void HotkeyType::FillMap() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
HotkeyManager Hotkeys;
|
HotkeyManager Hotkeys;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
///
|
///
|
||||||
HotkeyManager::HotkeyManager() {
|
HotkeyManager::HotkeyManager() {
|
||||||
modified = false;
|
modified = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
///
|
///
|
||||||
HotkeyManager::~HotkeyManager() {
|
HotkeyManager::~HotkeyManager() {
|
||||||
key.clear();
|
key.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Save
|
/// @brief Save
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -278,8 +256,6 @@ void HotkeyManager::Save() {
|
||||||
modified = false;
|
modified = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Load
|
/// @brief Load
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -353,14 +329,11 @@ void HotkeyManager::Load() {
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set all hotkeys to the default values
|
/// @brief Set all hotkeys to the default values
|
||||||
///
|
///
|
||||||
void HotkeyManager::LoadDefaults() {
|
void HotkeyManager::LoadDefaults() {
|
||||||
modified = true;
|
modified = true;
|
||||||
|
|
||||||
|
|
||||||
/// @note () is used here instead of _T(). This is done so the strings can be extracted.
|
/// @note () is used here instead of _T(). This is done so the strings can be extracted.
|
||||||
/// However, since this function is called before locale is set, it won't ever be translated.
|
/// However, since this function is called before locale is set, it won't ever be translated.
|
||||||
/// Keep this in mind: THESE CANNOT BE TRANSLATED HERE!
|
/// Keep this in mind: THESE CANNOT BE TRANSLATED HERE!
|
||||||
|
@ -503,8 +476,6 @@ void HotkeyManager::LoadDefaults() {
|
||||||
SetHotkey(_("Visual Tool Vector Clip"), _T("J"));
|
SetHotkey(_("Visual Tool Vector Clip"), _T("J"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set hotkey
|
/// @brief Set hotkey
|
||||||
/// @param function
|
/// @param function
|
||||||
/// @param hotkey
|
/// @param hotkey
|
||||||
|
@ -514,7 +485,6 @@ void HotkeyManager::SetHotkey(wxString function,HotkeyType hotkey) {
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param function
|
/// @param function
|
||||||
/// @param hotkey
|
/// @param hotkey
|
||||||
|
@ -524,8 +494,6 @@ void HotkeyManager::SetHotkey(wxString function,wxString hotkey) {
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set file
|
/// @brief Set file
|
||||||
/// @param file
|
/// @param file
|
||||||
///
|
///
|
||||||
|
@ -533,8 +501,6 @@ void HotkeyManager::SetFile(wxString file) {
|
||||||
filename = file;
|
filename = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get hotkey as text
|
/// @brief Get hotkey as text
|
||||||
/// @param function
|
/// @param function
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -547,8 +513,6 @@ const wxString HotkeyManager::GetText(wxString function) const {
|
||||||
else throw _T("Hotkey not defined");
|
else throw _T("Hotkey not defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get hotkey as accelerator entry
|
/// @brief Get hotkey as accelerator entry
|
||||||
/// @param function
|
/// @param function
|
||||||
/// @param id
|
/// @param id
|
||||||
|
@ -565,8 +529,6 @@ wxAcceleratorEntry HotkeyManager::GetAccelerator(wxString function,int id) const
|
||||||
else throw _T("Hotkey not defined");
|
else throw _T("Hotkey not defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set last key pressed
|
/// @brief Set last key pressed
|
||||||
/// @param keypress
|
/// @param keypress
|
||||||
/// @param ctrl
|
/// @param ctrl
|
||||||
|
@ -581,8 +543,6 @@ void HotkeyManager::SetPressed(int keypress,bool ctrl,bool alt,bool shift) {
|
||||||
if (shift) lastMod |= wxACCEL_SHIFT;
|
if (shift) lastMod |= wxACCEL_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Is pressed?
|
/// @brief Is pressed?
|
||||||
/// @param function
|
/// @param function
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -596,8 +556,6 @@ bool HotkeyManager::IsPressed(wxString function) const {
|
||||||
else throw _T("Hotkey not defined");
|
else throw _T("Hotkey not defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Search for a hotkey
|
/// @brief Search for a hotkey
|
||||||
/// @param keycode
|
/// @param keycode
|
||||||
/// @param mod
|
/// @param mod
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <libaegisub/exception.h>
|
||||||
#include "factory_manager.h"
|
#include "factory_manager.h"
|
||||||
|
|
||||||
/// @class AudioProvider
|
/// @class AudioProvider
|
||||||
|
@ -88,6 +89,9 @@ public:
|
||||||
virtual bool AreSamplesNativeEndian() const = 0;
|
virtual bool AreSamplesNativeEndian() const = 0;
|
||||||
|
|
||||||
void GetWaveForm(int *min,int *peak,int64_t start,int w,int h,int samples,float scale);
|
void GetWaveForm(int *min,int *peak,int64_t start,int w,int h,int samples,float scale);
|
||||||
|
|
||||||
|
/// @brief Does this provider benefit from external caching?
|
||||||
|
virtual bool NeedsCache() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
|
@ -100,3 +104,9 @@ public:
|
||||||
static void RegisterProviders();
|
static void RegisterProviders();
|
||||||
static AudioProvider *GetProvider(wxString filename, int cache=-1);
|
static AudioProvider *GetProvider(wxString filename, int cache=-1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DEFINE_BASE_EXCEPTION_NOINNER(AudioProviderError, agi::Exception);
|
||||||
|
DEFINE_SIMPLE_EXCEPTION_NOINNER(AudioOpenError, AudioProviderError, "audio/open/failed");
|
||||||
|
|
||||||
|
/// Error of some sort occurred while decoding a frame
|
||||||
|
DEFINE_SIMPLE_EXCEPTION_NOINNER(AudioDecodeError, AudioProviderError, "audio/error");
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "video_frame.h"
|
#include "video_frame.h"
|
||||||
|
#include <libaegisub/exception.h>
|
||||||
#include <libaegisub/vfr.h>
|
#include <libaegisub/vfr.h>
|
||||||
|
|
||||||
/// @class VideoProvider
|
/// @class VideoProvider
|
||||||
|
@ -69,3 +70,12 @@ public:
|
||||||
/// @return Returns true if caching is desired, false otherwise.
|
/// @return Returns true if caching is desired, false otherwise.
|
||||||
virtual bool WantsCaching() const { return false; }
|
virtual bool WantsCaching() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DEFINE_BASE_EXCEPTION_NOINNER(VideoProviderError, agi::Exception);
|
||||||
|
/// File could be opened, but is not a supported format
|
||||||
|
DEFINE_SIMPLE_EXCEPTION_NOINNER(VideoNotSupported, VideoProviderError, "video/open/notsupported");
|
||||||
|
/// File appears to be a supported format, but could not be opened
|
||||||
|
DEFINE_SIMPLE_EXCEPTION_NOINNER(VideoOpenError, VideoProviderError, "video/open/failed");
|
||||||
|
|
||||||
|
/// Error of some sort occurred while decoding a frame
|
||||||
|
DEFINE_SIMPLE_EXCEPTION_NOINNER(VideoDecodeError, VideoProviderError, "video/error");
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
@ -54,33 +53,24 @@
|
||||||
#include <libaegisub/vfr.h>
|
#include <libaegisub/vfr.h>
|
||||||
#include "mkv_wrap.h"
|
#include "mkv_wrap.h"
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
MatroskaWrapper MatroskaWrapper::wrapper;
|
MatroskaWrapper MatroskaWrapper::wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
#define CACHESIZE 65536
|
#define CACHESIZE 65536
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
///
|
///
|
||||||
MatroskaWrapper::MatroskaWrapper() {
|
MatroskaWrapper::MatroskaWrapper() {
|
||||||
file = NULL;
|
file = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
///
|
///
|
||||||
MatroskaWrapper::~MatroskaWrapper() {
|
MatroskaWrapper::~MatroskaWrapper() {
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Open file
|
/// @brief Open file
|
||||||
/// @param filename
|
/// @param filename
|
||||||
/// @param parse
|
/// @param parse
|
||||||
|
@ -112,8 +102,6 @@ void MatroskaWrapper::Open(wxString filename,bool parse) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Close file
|
/// @brief Close file
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -127,8 +115,6 @@ void MatroskaWrapper::Close() {
|
||||||
timecodes.clear();
|
timecodes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Return keyframes
|
/// @brief Return keyframes
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -136,8 +122,6 @@ std::vector<int> MatroskaWrapper::GetKeyFrames() {
|
||||||
return keyFrames;
|
return keyFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Comparison operator
|
/// @brief Comparison operator
|
||||||
/// @param t1
|
/// @param t1
|
||||||
/// @param t2
|
/// @param t2
|
||||||
|
@ -147,8 +131,6 @@ bool operator < (MkvFrame &t1, MkvFrame &t2) {
|
||||||
return t1.time < t2.time;
|
return t1.time < t2.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Actually parse
|
/// @brief Actually parse
|
||||||
///
|
///
|
||||||
void MatroskaWrapper::Parse() {
|
void MatroskaWrapper::Parse() {
|
||||||
|
@ -200,7 +182,7 @@ void MatroskaWrapper::Parse() {
|
||||||
// Cancelled?
|
// Cancelled?
|
||||||
if (canceled) {
|
if (canceled) {
|
||||||
Close();
|
Close();
|
||||||
throw _T("Canceled");
|
throw agi::UserCancelException("Canceled");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identical to (frameN % 2048) == 0,
|
// Identical to (frameN % 2048) == 0,
|
||||||
|
@ -257,7 +239,6 @@ void MatroskaWrapper::Parse() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int mkv_round(double num) {
|
static int mkv_round(double num) {
|
||||||
return (int)(num + .5);
|
return (int)(num + .5);
|
||||||
}
|
}
|
||||||
|
@ -275,8 +256,6 @@ void MatroskaWrapper::SetToTimecodes(agi::vfr::Framerate &target) {
|
||||||
target = agi::vfr::Framerate(times);
|
target = agi::vfr::Framerate(times);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get subtitles
|
/// @brief Get subtitles
|
||||||
/// @param target
|
/// @param target
|
||||||
///
|
///
|
||||||
|
@ -330,7 +309,7 @@ void MatroskaWrapper::GetSubtitles(AssFile *target) {
|
||||||
if (choice == -1) {
|
if (choice == -1) {
|
||||||
target->LoadDefault(true);
|
target->LoadDefault(true);
|
||||||
Close();
|
Close();
|
||||||
throw _T("Canceled.");
|
throw agi::UserCancelException("cancelled");
|
||||||
}
|
}
|
||||||
trackToRead = tracksFound[choice];
|
trackToRead = tracksFound[choice];
|
||||||
}
|
}
|
||||||
|
@ -398,7 +377,7 @@ void MatroskaWrapper::GetSubtitles(AssFile *target) {
|
||||||
if (canceled) {
|
if (canceled) {
|
||||||
target->LoadDefault(true);
|
target->LoadDefault(true);
|
||||||
Close();
|
Close();
|
||||||
throw _T("Canceled");
|
throw agi::UserCancelException("cancelled");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read to temp
|
// Read to temp
|
||||||
|
@ -525,7 +504,6 @@ bool MatroskaWrapper::HasSubtitles(wxString const& filename) {
|
||||||
#define std_ftell ftello
|
#define std_ftell ftello
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/// @brief STDIO class
|
/// @brief STDIO class
|
||||||
/// @param _st
|
/// @param _st
|
||||||
/// @param pos
|
/// @param pos
|
||||||
|
@ -577,7 +555,6 @@ longlong StdIoScan(InputStream *_st, ulonglong start, unsigned signature) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief This is used to limit readahead.
|
/// @brief This is used to limit readahead.
|
||||||
/// @param _st
|
/// @param _st
|
||||||
/// @return Cache size
|
/// @return Cache size
|
||||||
|
@ -586,7 +563,6 @@ unsigned StdIoGetCacheSize(InputStream *_st) {
|
||||||
return CACHESIZE;
|
return CACHESIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get last error message
|
/// @brief Get last error message
|
||||||
/// @param _st
|
/// @param _st
|
||||||
/// @return Last error message
|
/// @return Last error message
|
||||||
|
@ -596,7 +572,6 @@ const char *StdIoGetLastError(InputStream *_st) {
|
||||||
return strerror(st->error);
|
return strerror(st->error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Memory allocation, this is done via stdlib
|
/// @brief Memory allocation, this is done via stdlib
|
||||||
/// @param _st
|
/// @param _st
|
||||||
/// @param size
|
/// @param size
|
||||||
|
@ -606,7 +581,6 @@ void *StdIoMalloc(InputStream *_st, size_t size) {
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param _st
|
/// @param _st
|
||||||
/// @param mem
|
/// @param mem
|
||||||
|
@ -617,7 +591,6 @@ void *StdIoRealloc(InputStream *_st, void *mem, size_t size) {
|
||||||
return realloc(mem,size);
|
return realloc(mem,size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param _st
|
/// @param _st
|
||||||
/// @param mem
|
/// @param mem
|
||||||
|
@ -626,7 +599,6 @@ void StdIoFree(InputStream *_st, void *mem) {
|
||||||
free(mem);
|
free(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param _st
|
/// @param _st
|
||||||
/// @param cur
|
/// @param cur
|
||||||
|
@ -637,7 +609,6 @@ int StdIoProgress(InputStream *_st, ulonglong cur, ulonglong max) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param _st
|
/// @param _st
|
||||||
/// @return
|
/// @return
|
||||||
|
@ -652,7 +623,6 @@ longlong StdIoGetFileSize(InputStream *_st) {
|
||||||
return epos;
|
return epos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @param filename
|
/// @param filename
|
||||||
///
|
///
|
||||||
|
@ -673,4 +643,3 @@ MkvStdIO::MkvStdIO(wxString filename) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -64,8 +64,6 @@ public:
|
||||||
int error;
|
int error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class MkvFrame
|
/// @class MkvFrame
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
|
@ -83,7 +81,6 @@ public:
|
||||||
/// DOCME
|
/// DOCME
|
||||||
int64_t filePos;
|
int64_t filePos;
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
///
|
///
|
||||||
MkvFrame() {
|
MkvFrame() {
|
||||||
|
@ -107,7 +104,6 @@ public:
|
||||||
bool operator < (MkvFrame &t1, MkvFrame &t2);
|
bool operator < (MkvFrame &t1, MkvFrame &t2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class MatroskaWrapper
|
/// @class MatroskaWrapper
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
|
@ -142,7 +138,6 @@ public:
|
||||||
MatroskaWrapper();
|
MatroskaWrapper();
|
||||||
~MatroskaWrapper();
|
~MatroskaWrapper();
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
|
@ -166,9 +161,6 @@ public:
|
||||||
void GetSubtitles(AssFile *target);
|
void GetSubtitles(AssFile *target);
|
||||||
static bool HasSubtitles(wxString const& filename);
|
static bool HasSubtitles(wxString const& filename);
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
static MatroskaWrapper wrapper;
|
static MatroskaWrapper wrapper;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,12 +34,8 @@
|
||||||
/// @ingroup spelling
|
/// @ingroup spelling
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_HUNSPELL
|
#ifdef WITH_HUNSPELL
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
|
@ -51,7 +47,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
#include <hunspell/hunspell.hxx>
|
|
||||||
|
|
||||||
#include "charset_conv.h"
|
#include "charset_conv.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
@ -62,7 +57,6 @@
|
||||||
#include "text_file_writer.h"
|
#include "text_file_writer.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
HunspellSpellChecker::HunspellSpellChecker() {
|
HunspellSpellChecker::HunspellSpellChecker() {
|
||||||
hunspell = NULL;
|
hunspell = NULL;
|
||||||
|
@ -71,15 +65,11 @@ HunspellSpellChecker::HunspellSpellChecker() {
|
||||||
SetLanguage(lagi_wxString(OPT_GET("Tool/Spell Checker/Language")->GetString()));
|
SetLanguage(lagi_wxString(OPT_GET("Tool/Spell Checker/Language")->GetString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
HunspellSpellChecker::~HunspellSpellChecker() {
|
HunspellSpellChecker::~HunspellSpellChecker() {
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Reset spelling library
|
/// @brief Reset spelling library
|
||||||
void HunspellSpellChecker::Reset() {
|
void HunspellSpellChecker::Reset() {
|
||||||
delete hunspell;
|
delete hunspell;
|
||||||
|
@ -92,8 +82,6 @@ void HunspellSpellChecker::Reset() {
|
||||||
dicpath.Clear();
|
dicpath.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Can add to dictionary?
|
/// @brief Can add to dictionary?
|
||||||
/// @param word Word to check.
|
/// @param word Word to check.
|
||||||
/// @return Whether word can be added or not.
|
/// @return Whether word can be added or not.
|
||||||
|
@ -109,8 +97,6 @@ bool HunspellSpellChecker::CanAddWord(wxString word) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Add word to dictionary
|
/// @brief Add word to dictionary
|
||||||
/// @param word Word to add.
|
/// @param word Word to add.
|
||||||
///
|
///
|
||||||
|
@ -171,8 +157,6 @@ void HunspellSpellChecker::AddWord(wxString word) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Check if the word is valid.
|
/// @brief Check if the word is valid.
|
||||||
/// @param word Word to check
|
/// @param word Word to check
|
||||||
/// @return Whether word is valid or not.
|
/// @return Whether word is valid or not.
|
||||||
|
@ -187,8 +171,6 @@ bool HunspellSpellChecker::CheckWord(wxString word) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get suggestions for word.
|
/// @brief Get suggestions for word.
|
||||||
/// @param word Word to get suggestions for
|
/// @param word Word to get suggestions for
|
||||||
/// @return List of suggestions
|
/// @return List of suggestions
|
||||||
|
@ -217,8 +199,6 @@ wxArrayString HunspellSpellChecker::GetSuggestions(wxString word) {
|
||||||
return suggestions;
|
return suggestions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Get list of available dictionaries.
|
/// @brief Get list of available dictionaries.
|
||||||
/// @return List of available dictionaries
|
/// @return List of available dictionaries
|
||||||
///
|
///
|
||||||
|
@ -252,8 +232,6 @@ wxArrayString HunspellSpellChecker::GetLanguageList() {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set language.
|
/// @brief Set language.
|
||||||
/// @param language Language to set
|
/// @param language Language to set
|
||||||
///
|
///
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "subtitles_provider_csri.h"
|
#include "subtitles_provider_csri.h"
|
||||||
#include "text_file_writer.h"
|
#include "text_file_writer.h"
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
|
#include "video_frame.h"
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param type
|
/// @param type
|
||||||
|
|
|
@ -41,10 +41,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <wx/string.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <libaegisub/io.h>
|
#include <libaegisub/io.h>
|
||||||
|
|
|
@ -67,8 +67,7 @@ AegiVideoFrame const& ThreadedFrameSource::ProcFrame(int frameNum, double time,
|
||||||
try {
|
try {
|
||||||
frame->CopyFrom(videoProvider->GetFrame(frameNum));
|
frame->CopyFrom(videoProvider->GetFrame(frameNum));
|
||||||
}
|
}
|
||||||
catch (const wchar_t *err) { throw VideoProviderErrorEvent(err); }
|
catch (VideoProviderError const& err) { throw VideoProviderErrorEvent(err); }
|
||||||
catch (wxString const& err) { throw VideoProviderErrorEvent(err); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This deliberately results in a call to LoadSubtitles while a render
|
// This deliberately results in a call to LoadSubtitles while a render
|
||||||
|
@ -107,7 +106,6 @@ AegiVideoFrame const& ThreadedFrameSource::ProcFrame(int frameNum, double time,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const wchar_t *err) { throw SubtitlesProviderErrorEvent(err); }
|
|
||||||
catch (wxString const& err) { throw SubtitlesProviderErrorEvent(err); }
|
catch (wxString const& err) { throw SubtitlesProviderErrorEvent(err); }
|
||||||
|
|
||||||
provider->DrawSubtitles(*frame, time);
|
provider->DrawSubtitles(*frame, time);
|
||||||
|
@ -200,13 +198,13 @@ wxDEFINE_EVENT(EVT_FRAME_READY, FrameReadyEvent);
|
||||||
wxDEFINE_EVENT(EVT_VIDEO_ERROR, VideoProviderErrorEvent);
|
wxDEFINE_EVENT(EVT_VIDEO_ERROR, VideoProviderErrorEvent);
|
||||||
wxDEFINE_EVENT(EVT_SUBTITLES_ERROR, SubtitlesProviderErrorEvent);
|
wxDEFINE_EVENT(EVT_SUBTITLES_ERROR, SubtitlesProviderErrorEvent);
|
||||||
|
|
||||||
VideoProviderErrorEvent::VideoProviderErrorEvent(wxString msg)
|
VideoProviderErrorEvent::VideoProviderErrorEvent(VideoProviderError const& err)
|
||||||
: agi::Exception(STD_STR(msg), NULL)
|
: agi::Exception(err.GetMessage(), &err)
|
||||||
{
|
{
|
||||||
SetEventType(EVT_VIDEO_ERROR);
|
SetEventType(EVT_VIDEO_ERROR);
|
||||||
}
|
}
|
||||||
SubtitlesProviderErrorEvent::SubtitlesProviderErrorEvent(wxString msg)
|
SubtitlesProviderErrorEvent::SubtitlesProviderErrorEvent(wxString err)
|
||||||
: agi::Exception(STD_STR(msg), NULL)
|
: agi::Exception(err, NULL)
|
||||||
{
|
{
|
||||||
SetEventType(EVT_SUBTITLES_ERROR);
|
SetEventType(EVT_SUBTITLES_ERROR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
class AssFile;
|
class AssFile;
|
||||||
class SubtitlesProvider;
|
class SubtitlesProvider;
|
||||||
class VideoProvider;
|
class VideoProvider;
|
||||||
|
class VideoProviderError;
|
||||||
|
|
||||||
/// @class ThreadedFrameSource
|
/// @class ThreadedFrameSource
|
||||||
/// @brief An asynchronous video decoding and subtitle rendering wrapper
|
/// @brief An asynchronous video decoding and subtitle rendering wrapper
|
||||||
|
@ -155,7 +156,7 @@ public:
|
||||||
const char * GetName() const { return "video/error"; }
|
const char * GetName() const { return "video/error"; }
|
||||||
wxEvent *Clone() const { return new VideoProviderErrorEvent(*this); };
|
wxEvent *Clone() const { return new VideoProviderErrorEvent(*this); };
|
||||||
agi::Exception *Copy() const { return new VideoProviderErrorEvent(*this); };
|
agi::Exception *Copy() const { return new VideoProviderErrorEvent(*this); };
|
||||||
VideoProviderErrorEvent(wxString msg);
|
VideoProviderErrorEvent(VideoProviderError const& err);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SubtitlesProviderErrorEvent : public wxEvent, public agi::Exception {
|
class SubtitlesProviderErrorEvent : public wxEvent, public agi::Exception {
|
||||||
|
|
|
@ -34,9 +34,6 @@
|
||||||
/// @ingroup main_ui video
|
/// @ingroup main_ui video
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
////////////
|
|
||||||
// Includes
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
|
@ -44,7 +41,6 @@
|
||||||
#include <wx/mimetype.h>
|
#include <wx/mimetype.h>
|
||||||
#include <wx/rawbmp.h>
|
#include <wx/rawbmp.h>
|
||||||
#include <wx/statline.h>
|
#include <wx/statline.h>
|
||||||
#include <wx/tglbtn.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ass_dialogue.h"
|
#include "ass_dialogue.h"
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
#include "video_box.h"
|
#include "video_box.h"
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
#include "video_display.h"
|
#include "video_display.h"
|
||||||
|
#include "video_frame.h"
|
||||||
|
|
||||||
/// IDs
|
/// IDs
|
||||||
enum {
|
enum {
|
||||||
|
@ -196,11 +197,13 @@ void VideoContext::SetVideo(const wxString &filename) {
|
||||||
|
|
||||||
UpdateDisplays(true);
|
UpdateDisplays(true);
|
||||||
}
|
}
|
||||||
catch (const wchar_t *e) {
|
catch (agi::UserCancelException const&) { }
|
||||||
wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK);
|
catch (agi::FileNotAccessibleError const& err) {
|
||||||
|
config::mru->Remove("Video", STD_STR(filename));
|
||||||
|
wxMessageBox(lagi_wxString(err.GetMessage()), L"Error setting video", wxICON_ERROR | wxOK);
|
||||||
}
|
}
|
||||||
catch (const wxString &e) {
|
catch (VideoProviderError const& err) {
|
||||||
wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK);
|
wxMessageBox(lagi_wxString(err.GetMessage()), L"Error setting video", wxICON_ERROR | wxOK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,17 +49,9 @@
|
||||||
#error "Aegisub requires wxWidgets to be compiled with OpenGL support."
|
#error "Aegisub requires wxWidgets to be compiled with OpenGL support."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include <OpenGL/GL.h>
|
|
||||||
#include <OpenGL/glu.h>
|
|
||||||
#else
|
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <GL/glu.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <libaegisub/vfr.h>
|
#include <libaegisub/vfr.h>
|
||||||
#include "video_frame.h"
|
|
||||||
|
|
||||||
|
class AegiVideoFrame;
|
||||||
class SubtitlesGrid;
|
class SubtitlesGrid;
|
||||||
class AudioProvider;
|
class AudioProvider;
|
||||||
class AudioDisplay;
|
class AudioDisplay;
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "charset_conv.h"
|
#include "charset_conv.h"
|
||||||
|
#include "compat.h"
|
||||||
#include "gl_wrap.h"
|
#include "gl_wrap.h"
|
||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
#include "mkv_wrap.h"
|
#include "mkv_wrap.h"
|
||||||
|
@ -51,174 +52,159 @@
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
#include "video_provider_avs.h"
|
#include "video_provider_avs.h"
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param _filename
|
/// @param _filename
|
||||||
///
|
///
|
||||||
AvisynthVideoProvider::AvisynthVideoProvider(wxString _filename) {
|
AvisynthVideoProvider::AvisynthVideoProvider(wxString filename) try
|
||||||
bool mpeg2dec3_priority = true;
|
: usedDirectShow(false)
|
||||||
RGB32Video = NULL;
|
, decoderName(_("Unknown"))
|
||||||
num_frames = 0;
|
, num_frames(0)
|
||||||
last_fnum = -1;
|
, last_fnum(-1)
|
||||||
KeyFrames.clear();
|
, RGB32Video(NULL)
|
||||||
|
{
|
||||||
RGB32Video = OpenVideo(_filename,mpeg2dec3_priority);
|
RGB32Video = OpenVideo(filename);
|
||||||
|
|
||||||
vi = RGB32Video->GetVideoInfo();
|
vi = RGB32Video->GetVideoInfo();
|
||||||
}
|
}
|
||||||
|
catch (AvisynthError const& err) {
|
||||||
|
throw VideoOpenError("Avisynth error: " + std::string(err.msg));
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
///
|
|
||||||
AvisynthVideoProvider::~AvisynthVideoProvider() {
|
AvisynthVideoProvider::~AvisynthVideoProvider() {
|
||||||
iframe.Clear();
|
iframe.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Actually open the video into Avisynth
|
AVSValue AvisynthVideoProvider::Open(wxFileName const& fname, wxString const& extension) {
|
||||||
/// @param _filename
|
char *videoFilename = env->SaveString(fname.GetShortPath().mb_str(csConvLocal));
|
||||||
/// @param mpeg2dec3_priority
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priority) {
|
|
||||||
wxMutexLocker lock(AviSynthMutex);
|
|
||||||
AVSValue script;
|
|
||||||
|
|
||||||
usedDirectShow = false;
|
// Avisynth file, just import it
|
||||||
decoderName = _("Unknown");
|
if (extension == L".avs") {
|
||||||
|
LOG_I("avisynth/video") << "Opening .avs file with Import";
|
||||||
|
decoderName = L"Import";
|
||||||
|
return env->Invoke("Import", videoFilename);
|
||||||
|
}
|
||||||
|
|
||||||
wxString extension = _filename.Right(4);
|
// Open avi file with AviSource
|
||||||
extension.LowerCase();
|
if (extension == L".avi") {
|
||||||
|
LOG_I("avisynth/video") << "Opening .avi file with AviSource";
|
||||||
try {
|
try {
|
||||||
// Prepare filename
|
const char *argnames[2] = { 0, "audio" };
|
||||||
//char *videoFilename = env->SaveString(_filename.mb_str(wxConvLocal));
|
AVSValue args[2] = { videoFilename, false };
|
||||||
wxFileName fname(_filename);
|
decoderName = L"AviSource";
|
||||||
char *videoFilename = env->SaveString(fname.GetShortPath().mb_str(csConvLocal));
|
return env->Invoke("AviSource", AVSValue(args,2), argnames);
|
||||||
|
|
||||||
// Avisynth file, just import it
|
|
||||||
if (extension == _T(".avs")) {
|
|
||||||
LOG_I("avisynth/video") << "Opening .avs file with Import";
|
|
||||||
script = env->Invoke("Import", videoFilename);
|
|
||||||
decoderName = _T("Import");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open avi file with AviSource
|
// On Failure, fallback to DSS
|
||||||
else if (extension == _T(".avi")) {
|
catch (AvisynthError &) {
|
||||||
LOG_I("avisynth/video") << "Opening .avi file with AviSource";
|
LOG_I("avisynth/video") << "Failed to open .avi file with AviSource, switching to DirectShowSource";
|
||||||
try {
|
|
||||||
const char *argnames[2] = { 0, "audio" };
|
|
||||||
AVSValue args[2] = { videoFilename, false };
|
|
||||||
script = env->Invoke("AviSource", AVSValue(args,2), argnames);
|
|
||||||
decoderName = _T("AviSource");
|
|
||||||
}
|
|
||||||
|
|
||||||
// On Failure, fallback to DSS
|
|
||||||
catch (AvisynthError &) {
|
|
||||||
LOG_I("avisynth/video") << "Failed to open .avi file with AviSource, switching to DirectShowSource";
|
|
||||||
goto directshowOpen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open d2v with mpeg2dec3
|
|
||||||
else if (extension == _T(".d2v") && env->FunctionExists("Mpeg2Dec3_Mpeg2Source") && mpeg2dec3_priority) {
|
|
||||||
LOG_I("avisynth/video") << "Opening .d2v file with Mpeg2Dec3_Mpeg2Source";
|
|
||||||
script = env->Invoke("Mpeg2Dec3_Mpeg2Source", videoFilename);
|
|
||||||
decoderName = _T("Mpeg2Dec3_Mpeg2Source");
|
|
||||||
|
|
||||||
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
|
|
||||||
if (env->FunctionExists("SetPlanarLegacyAlignment")) {
|
|
||||||
AVSValue args[2] = { script, true };
|
|
||||||
script = env->Invoke("SetPlanarLegacyAlignment", AVSValue(args,2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If that fails, try opening it with DGDecode
|
|
||||||
else if (extension == _T(".d2v") && env->FunctionExists("DGDecode_Mpeg2Source")) {
|
|
||||||
LOG_I("avisynth/video") << "Opening .d2v file with DGDecode_Mpeg2Source";
|
|
||||||
script = env->Invoke("Mpeg2Source", videoFilename);
|
|
||||||
decoderName = _T("DGDecode_Mpeg2Source");
|
|
||||||
|
|
||||||
//note that DGDecode will also have issues like if the version is too ancient but no sane person
|
|
||||||
//would use that anyway
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (extension == _T(".d2v") && env->FunctionExists("Mpeg2Source")) {
|
|
||||||
LOG_I("avisynth/video") << "Opening .d2v file with other Mpeg2Source";
|
|
||||||
script = env->Invoke("Mpeg2Source", videoFilename);
|
|
||||||
decoderName = _T("Mpeg2Source");
|
|
||||||
|
|
||||||
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
|
|
||||||
if (env->FunctionExists("SetPlanarLegacyAlignment"))
|
|
||||||
script = env->Invoke("SetPlanarLegacyAlignment", script);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some other format, such as mkv, mp4, ogm... try both flavors of DirectShowSource
|
|
||||||
else {
|
|
||||||
directshowOpen:
|
|
||||||
|
|
||||||
// Try loading DirectShowSource2
|
|
||||||
bool dss2 = false;
|
|
||||||
if (env->FunctionExists("dss2")) dss2 = true;
|
|
||||||
if (!dss2) {
|
|
||||||
wxFileName dss2path(StandardPaths::DecodePath(_T("?data/avss.dll")));
|
|
||||||
if (dss2path.FileExists()) {
|
|
||||||
env->Invoke("LoadPlugin",env->SaveString(dss2path.GetFullPath().mb_str(csConvLocal)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If DSS2 loaded properly, try using it
|
|
||||||
dss2 = false;
|
|
||||||
if (env->FunctionExists("dss2")) {
|
|
||||||
LOG_I("avisynth/video") << "Opening video with DSS2";
|
|
||||||
script = env->Invoke("DSS2", videoFilename);
|
|
||||||
dss2 = true;
|
|
||||||
decoderName = _T("DSS2");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try DirectShowSource
|
|
||||||
if (!dss2) {
|
|
||||||
// Load DirectShowSource.dll from app dir if it exists
|
|
||||||
wxFileName dsspath(StandardPaths::DecodePath(_T("?data/DirectShowSource.dll")));
|
|
||||||
if (dsspath.FileExists()) {
|
|
||||||
env->Invoke("LoadPlugin",env->SaveString(dsspath.GetFullPath().mb_str(csConvLocal)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then try using DSS
|
|
||||||
if (env->FunctionExists("DirectShowSource")) {
|
|
||||||
const char *argnames[3] = { 0, "video", "audio" };
|
|
||||||
AVSValue args[3] = { videoFilename, true, false };
|
|
||||||
LOG_I("avisynth/video") << "Opening video with DirectShowSource";
|
|
||||||
script = env->Invoke("DirectShowSource", AVSValue(args,3), argnames);
|
|
||||||
usedDirectShow = true;
|
|
||||||
decoderName = _T("DirectShowSource");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Failed to find a suitable function
|
|
||||||
else {
|
|
||||||
LOG_E("avisynth/video") << "DSS function not found";
|
|
||||||
throw AvisynthError("No function suitable for opening the video found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catch errors
|
// Open d2v with mpeg2dec3
|
||||||
catch (AvisynthError &err) {
|
if (extension == L".d2v" && env->FunctionExists("Mpeg2Dec3_Mpeg2Source")) {
|
||||||
LOG_E("avisynth/video") << "Avisynth error: " << err.msg;
|
LOG_I("avisynth/video") << "Opening .d2v file with Mpeg2Dec3_Mpeg2Source";
|
||||||
throw _T("AviSynth error: ") + wxString(err.msg,csConvLocal);
|
AVSValue script = env->Invoke("Mpeg2Dec3_Mpeg2Source", videoFilename);
|
||||||
|
decoderName = L"Mpeg2Dec3_Mpeg2Source";
|
||||||
|
|
||||||
|
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
|
||||||
|
if (env->FunctionExists("SetPlanarLegacyAlignment")) {
|
||||||
|
AVSValue args[2] = { script, true };
|
||||||
|
script = env->Invoke("SetPlanarLegacyAlignment", AVSValue(args,2));
|
||||||
|
}
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If that fails, try opening it with DGDecode
|
||||||
|
if (extension == L".d2v" && env->FunctionExists("DGDecode_Mpeg2Source")) {
|
||||||
|
LOG_I("avisynth/video") << "Opening .d2v file with DGDecode_Mpeg2Source";
|
||||||
|
decoderName = L"DGDecode_Mpeg2Source";
|
||||||
|
return env->Invoke("Mpeg2Source", videoFilename);
|
||||||
|
|
||||||
|
//note that DGDecode will also have issues like if the version is too ancient but no sane person
|
||||||
|
//would use that anyway
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension == L".d2v" && env->FunctionExists("Mpeg2Source")) {
|
||||||
|
LOG_I("avisynth/video") << "Opening .d2v file with other Mpeg2Source";
|
||||||
|
AVSValue script = env->Invoke("Mpeg2Source", videoFilename);
|
||||||
|
decoderName = L"Mpeg2Source";
|
||||||
|
|
||||||
|
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
|
||||||
|
if (env->FunctionExists("SetPlanarLegacyAlignment"))
|
||||||
|
script = env->Invoke("SetPlanarLegacyAlignment", script);
|
||||||
|
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try loading DirectShowSource2
|
||||||
|
if (!env->FunctionExists("dss2")) {
|
||||||
|
wxFileName dss2path(StandardPaths::DecodePath(_T("?data/avss.dll")));
|
||||||
|
if (dss2path.FileExists()) {
|
||||||
|
env->Invoke("LoadPlugin",env->SaveString(dss2path.GetFullPath().mb_str(csConvLocal)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If DSS2 loaded properly, try using it
|
||||||
|
if (env->FunctionExists("dss2")) {
|
||||||
|
LOG_I("avisynth/video") << "Opening file with DSS2";
|
||||||
|
decoderName = L"DSS2";
|
||||||
|
return env->Invoke("DSS2", videoFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try DirectShowSource
|
||||||
|
// Load DirectShowSource.dll from app dir if it exists
|
||||||
|
wxFileName dsspath(StandardPaths::DecodePath(_T("?data/DirectShowSource.dll")));
|
||||||
|
if (dsspath.FileExists()) {
|
||||||
|
env->Invoke("LoadPlugin",env->SaveString(dsspath.GetFullPath().mb_str(csConvLocal)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then try using DSS
|
||||||
|
if (env->FunctionExists("DirectShowSource")) {
|
||||||
|
const char *argnames[3] = { 0, "video", "audio" };
|
||||||
|
AVSValue args[3] = { videoFilename, true, false };
|
||||||
|
usedDirectShow = true;
|
||||||
|
decoderName = L"DirectShowSource";
|
||||||
|
LOG_I("avisynth/video") << "Opening file with DirectShowSource";
|
||||||
|
return env->Invoke("DirectShowSource", AVSValue(args,3), argnames);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failed to find a suitable function
|
||||||
|
LOG_E("avisynth/video") << "DSS function not found";
|
||||||
|
throw VideoNotSupported("No function suitable for opening the video found");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Actually open the video into Avisynth
|
||||||
|
/// @param _filename
|
||||||
|
/// @return
|
||||||
|
///
|
||||||
|
PClip AvisynthVideoProvider::OpenVideo(wxString filename) {
|
||||||
|
wxMutexLocker lock(AviSynthMutex);
|
||||||
|
|
||||||
|
wxFileName fname(filename);
|
||||||
|
if (!fname.FileExists())
|
||||||
|
throw agi::FileNotFoundError(STD_STR(filename));
|
||||||
|
|
||||||
|
AVSValue script;
|
||||||
|
wxString extension = filename.Right(4).Lower();
|
||||||
|
try {
|
||||||
|
script = Open(fname, extension);
|
||||||
|
}
|
||||||
|
catch (AvisynthError const& err) {
|
||||||
|
throw VideoOpenError("Avisynth error: " + std::string(err.msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if video was loaded properly
|
// Check if video was loaded properly
|
||||||
if (!script.IsClip() || !script.AsClip()->GetVideoInfo().HasVideo()) {
|
if (!script.IsClip() || !script.AsClip()->GetVideoInfo().HasVideo()) {
|
||||||
LOG_E("avisynth/video") << "AvisynthVideoProvider::OpenVideo: No suitable video found";
|
throw VideoNotSupported("No usable video found");
|
||||||
throw _T("Avisynth: No usable video found in ") + _filename;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read keyframes and timecodes from MKV file
|
// Read keyframes and timecodes from MKV file
|
||||||
bool mkvOpen = MatroskaWrapper::wrapper.IsOpen();
|
bool mkvOpen = MatroskaWrapper::wrapper.IsOpen();
|
||||||
KeyFrames.clear();
|
KeyFrames.clear();
|
||||||
if (extension == _T(".mkv") || mkvOpen) {
|
if (extension == L".mkv" || mkvOpen) {
|
||||||
// Parse mkv
|
// Parse mkv
|
||||||
if (!mkvOpen) MatroskaWrapper::wrapper.Open(_filename);
|
if (!mkvOpen) MatroskaWrapper::wrapper.Open(filename);
|
||||||
|
|
||||||
// Get keyframes
|
// Get keyframes
|
||||||
KeyFrames = MatroskaWrapper::wrapper.GetKeyFrames();
|
KeyFrames = MatroskaWrapper::wrapper.GetKeyFrames();
|
||||||
|
@ -230,9 +216,9 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
||||||
}
|
}
|
||||||
// check if we have windows, if so we can load keyframes from AVI files using VFW
|
// check if we have windows, if so we can load keyframes from AVI files using VFW
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
else if (extension == _T(".avi")) {
|
else if (extension == L".avi") {
|
||||||
KeyFrames.clear();
|
KeyFrames.clear();
|
||||||
KeyFrames = VFWWrapper::GetKeyFrames(_filename);
|
KeyFrames = VFWWrapper::GetKeyFrames(filename);
|
||||||
}
|
}
|
||||||
#endif /* __WINDOWS__ */
|
#endif /* __WINDOWS__ */
|
||||||
|
|
||||||
|
@ -261,8 +247,6 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
||||||
return (env->Invoke("Cache", script)).AsClip();
|
return (env->Invoke("Cache", script)).AsClip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Actually get a frame
|
/// @brief Actually get a frame
|
||||||
/// @param _n
|
/// @param _n
|
||||||
/// @return
|
/// @return
|
||||||
|
|
|
@ -78,10 +78,11 @@ class AvisynthVideoProvider: public VideoProvider, AviSynthWrapper {
|
||||||
/// DOCME
|
/// DOCME
|
||||||
PClip RGB32Video;
|
PClip RGB32Video;
|
||||||
|
|
||||||
PClip OpenVideo(wxString _filename, bool mpeg2dec3_priority = true);
|
PClip OpenVideo(wxString filename);
|
||||||
|
AVSValue Open(wxFileName const& fname, wxString const& extension);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AvisynthVideoProvider(wxString _filename);
|
AvisynthVideoProvider(wxString filename);
|
||||||
~AvisynthVideoProvider();
|
~AvisynthVideoProvider();
|
||||||
|
|
||||||
const AegiVideoFrame GetFrame(int n);
|
const AegiVideoFrame GetFrame(int n);
|
||||||
|
|
|
@ -79,6 +79,4 @@ public:
|
||||||
virtual std::vector<int> GetKeyFrames() const { return master->GetKeyFrames(); }
|
virtual std::vector<int> GetKeyFrames() const { return master->GetKeyFrames(); }
|
||||||
virtual wxString GetWarning() const { return master->GetWarning(); }
|
virtual wxString GetWarning() const { return master->GetWarning(); }
|
||||||
virtual wxString GetDecoderName() const { return master->GetDecoderName(); }
|
virtual wxString GetDecoderName() const { return master->GetDecoderName(); }
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -122,12 +122,12 @@ DummyVideoProvider::DummyVideoProvider(wxString filename)
|
||||||
{
|
{
|
||||||
wxString params;
|
wxString params;
|
||||||
if (!filename.StartsWith(_T("?dummy:"), ¶ms)) {
|
if (!filename.StartsWith(_T("?dummy:"), ¶ms)) {
|
||||||
throw _T("Attempted creating dummy video provider with non-dummy filename");
|
throw agi::FileNotFoundError("Attempted creating dummy video provider with non-dummy filename");
|
||||||
}
|
}
|
||||||
|
|
||||||
wxStringTokenizer t(params, _T(":"));
|
wxStringTokenizer t(params, _T(":"));
|
||||||
if (t.CountTokens() < 7) {
|
if (t.CountTokens() < 7) {
|
||||||
throw _T("Too few fields in dummy video parameter list");
|
throw VideoOpenError("Too few fields in dummy video parameter list");
|
||||||
}
|
}
|
||||||
|
|
||||||
double fps;
|
double fps;
|
||||||
|
@ -136,37 +136,37 @@ DummyVideoProvider::DummyVideoProvider(wxString filename)
|
||||||
|
|
||||||
wxString field = t.GetNextToken();
|
wxString field = t.GetNextToken();
|
||||||
if (!field.ToDouble(&fps)) {
|
if (!field.ToDouble(&fps)) {
|
||||||
throw _T("Unable to parse fps field in dummy video parameter list");
|
throw VideoOpenError("Unable to parse fps field in dummy video parameter list");
|
||||||
}
|
}
|
||||||
|
|
||||||
field = t.GetNextToken();
|
field = t.GetNextToken();
|
||||||
if (!field.ToLong(&_frames)) {
|
if (!field.ToLong(&_frames)) {
|
||||||
throw _T("Unable to parse framecount field in dummy video parameter list");
|
throw VideoOpenError("Unable to parse framecount field in dummy video parameter list");
|
||||||
}
|
}
|
||||||
|
|
||||||
field = t.GetNextToken();
|
field = t.GetNextToken();
|
||||||
if (!field.ToLong(&_width)) {
|
if (!field.ToLong(&_width)) {
|
||||||
throw _T("Unable to parse width field in dummy video parameter list");
|
throw VideoOpenError("Unable to parse width field in dummy video parameter list");
|
||||||
}
|
}
|
||||||
|
|
||||||
field = t.GetNextToken();
|
field = t.GetNextToken();
|
||||||
if (!field.ToLong(&_height)) {
|
if (!field.ToLong(&_height)) {
|
||||||
throw _T("Unable to parse height field in dummy video parameter list");
|
throw VideoOpenError("Unable to parse height field in dummy video parameter list");
|
||||||
}
|
}
|
||||||
|
|
||||||
field = t.GetNextToken();
|
field = t.GetNextToken();
|
||||||
if (!field.ToLong(&red)) {
|
if (!field.ToLong(&red)) {
|
||||||
throw _T("Unable to parse red colour field in dummy video parameter list");
|
throw VideoOpenError("Unable to parse red colour field in dummy video parameter list");
|
||||||
}
|
}
|
||||||
|
|
||||||
field = t.GetNextToken();
|
field = t.GetNextToken();
|
||||||
if (!field.ToLong(&green)) {
|
if (!field.ToLong(&green)) {
|
||||||
throw _T("Unable to parse green colour field in dummy video parameter list");
|
throw VideoOpenError("Unable to parse green colour field in dummy video parameter list");
|
||||||
}
|
}
|
||||||
|
|
||||||
field = t.GetNextToken();
|
field = t.GetNextToken();
|
||||||
if (!field.ToLong(&blue)) {
|
if (!field.ToLong(&blue)) {
|
||||||
throw _T("Unable to parse bluecolour field in dummy video parameter list");
|
throw VideoOpenError("Unable to parse blue colour field in dummy video parameter list");
|
||||||
}
|
}
|
||||||
|
|
||||||
field = t.GetNextToken();
|
field = t.GetNextToken();
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "aegisub_endian.h"
|
#include "aegisub_endian.h"
|
||||||
#include "include/aegisub/aegisub.h"
|
#include "compat.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
#include "video_provider_ffmpegsource.h"
|
#include "video_provider_ffmpegsource.h"
|
||||||
|
@ -60,35 +60,41 @@
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param filename The filename to open
|
/// @param filename The filename to open
|
||||||
FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename) {
|
FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename)
|
||||||
COMInited = false;
|
: VideoSource(NULL)
|
||||||
|
, VideoInfo(NULL)
|
||||||
|
, Width(-1)
|
||||||
|
, Height(-1)
|
||||||
|
, FrameNumber(-1)
|
||||||
|
, COMInited(false)
|
||||||
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
HRESULT res;
|
HRESULT res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||||
res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
|
||||||
if (SUCCEEDED(res))
|
if (SUCCEEDED(res))
|
||||||
COMInited = true;
|
COMInited = true;
|
||||||
else if (res != RPC_E_CHANGED_MODE)
|
else if (res != RPC_E_CHANGED_MODE)
|
||||||
throw _T("FFmpegSource video provider: COM initialization failure");
|
throw VideoOpenError("COM initialization failure");
|
||||||
#endif
|
#endif
|
||||||
// initialize ffmpegsource
|
// initialize ffmpegsource
|
||||||
// FIXME: CPU detection?
|
// FIXME: CPU detection?
|
||||||
FFMS_Init(0);
|
FFMS_Init(0);
|
||||||
|
|
||||||
// clean up variables
|
|
||||||
VideoSource = NULL;
|
|
||||||
FrameNumber = -1;
|
|
||||||
ErrInfo.Buffer = FFMSErrMsg;
|
ErrInfo.Buffer = FFMSErrMsg;
|
||||||
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
|
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
|
||||||
ErrInfo.ErrorType = FFMS_ERROR_SUCCESS;
|
ErrInfo.ErrorType = FFMS_ERROR_SUCCESS;
|
||||||
ErrInfo.SubType = FFMS_ERROR_SUCCESS;
|
ErrInfo.SubType = FFMS_ERROR_SUCCESS;
|
||||||
ErrorMsg = _T("FFmpegSource video provider: ");
|
|
||||||
|
|
||||||
SetLogLevel();
|
SetLogLevel();
|
||||||
|
|
||||||
// and here we go
|
// and here we go
|
||||||
try {
|
try {
|
||||||
LoadVideo(filename);
|
LoadVideo(filename);
|
||||||
} catch (...) {
|
}
|
||||||
|
catch (wxString const& err) {
|
||||||
|
Close();
|
||||||
|
throw VideoOpenError(STD_STR(err));
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
Close();
|
Close();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
@ -98,32 +104,22 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename) {
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
FFmpegSourceVideoProvider::~FFmpegSourceVideoProvider() {
|
FFmpegSourceVideoProvider::~FFmpegSourceVideoProvider() {
|
||||||
Close();
|
Close();
|
||||||
#ifdef WIN32
|
|
||||||
if (COMInited)
|
|
||||||
CoUninitialize();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Opens video
|
/// @brief Opens video
|
||||||
/// @param filename The filename to open
|
/// @param filename The filename to open
|
||||||
void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
// make sure we don't have anything messy lying around
|
|
||||||
Close();
|
|
||||||
|
|
||||||
wxString FileNameShort = wxFileName(filename).GetShortPath();
|
wxString FileNameShort = wxFileName(filename).GetShortPath();
|
||||||
|
|
||||||
FFMS_Indexer *Indexer = FFMS_CreateIndexer(FileNameShort.utf8_str(), &ErrInfo);
|
FFMS_Indexer *Indexer = FFMS_CreateIndexer(FileNameShort.utf8_str(), &ErrInfo);
|
||||||
if (Indexer == NULL) {
|
if (Indexer == NULL) {
|
||||||
// error messages that can possibly contain a filename use this method instead of
|
throw agi::FileNotFoundError(ErrInfo.Buffer);
|
||||||
// wxString::Format because they may contain utf8 characters
|
|
||||||
ErrorMsg.Append(_T("Failed to create indexer: ")).Append(wxString(ErrInfo.Buffer, wxConvUTF8));
|
|
||||||
throw ErrorMsg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int,wxString> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_VIDEO);
|
std::map<int,wxString> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_VIDEO);
|
||||||
if (TrackList.size() <= 0)
|
if (TrackList.size() <= 0)
|
||||||
throw _T("FFmpegSource video provider: no video tracks found");
|
throw VideoNotSupported("no video tracks found");
|
||||||
|
|
||||||
// initialize the track number to an invalid value so we can detect later on
|
// initialize the track number to an invalid value so we can detect later on
|
||||||
// whether the user actually had to choose a track or not
|
// whether the user actually had to choose a track or not
|
||||||
|
@ -132,7 +128,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
TrackNumber = AskForTrackSelection(TrackList, FFMS_TYPE_VIDEO);
|
TrackNumber = AskForTrackSelection(TrackList, FFMS_TYPE_VIDEO);
|
||||||
// if it's still -1 here, user pressed cancel
|
// if it's still -1 here, user pressed cancel
|
||||||
if (TrackNumber == -1)
|
if (TrackNumber == -1)
|
||||||
throw _T("FFmpegSource video provider: video loading cancelled by user");
|
throw agi::UserCancelException("video loading cancelled by user");
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a name for the cache file
|
// generate a name for the cache file
|
||||||
|
@ -169,11 +165,9 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
try {
|
try {
|
||||||
// ignore audio decoding errors here, we don't care right now
|
// ignore audio decoding errors here, we don't care right now
|
||||||
Index = DoIndexing(Indexer, CacheName, TrackMask, FFMS_IEH_IGNORE);
|
Index = DoIndexing(Indexer, CacheName, TrackMask, FFMS_IEH_IGNORE);
|
||||||
} catch (wxString temp) {
|
}
|
||||||
ErrorMsg.Append(temp);
|
catch (wxString err) {
|
||||||
throw ErrorMsg;
|
throw VideoOpenError(STD_STR(err));
|
||||||
} catch (...) {
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,15 +186,14 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
if (TrackNumber < 0) {
|
if (TrackNumber < 0) {
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
Index = NULL;
|
Index = NULL;
|
||||||
ErrorMsg.Append(wxString::Format(_T("Couldn't find any video tracks: %s"), ErrInfo.Buffer));
|
throw VideoNotSupported(std::string("Couldn't find any video tracks: ") + ErrInfo.Buffer);
|
||||||
throw ErrorMsg;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set thread count
|
// set thread count
|
||||||
int Threads = OPT_GET("Provider/Video/FFmpegSource/Decoding Threads")->GetInt();
|
int Threads = OPT_GET("Provider/Video/FFmpegSource/Decoding Threads")->GetInt();
|
||||||
if (Threads < 1)
|
if (Threads < 1)
|
||||||
throw _T("FFmpegSource video provider: invalid decoding thread count");
|
throw VideoOpenError("invalid decoding thread count");
|
||||||
|
|
||||||
// set seekmode
|
// set seekmode
|
||||||
// TODO: give this its own option?
|
// TODO: give this its own option?
|
||||||
|
@ -214,8 +207,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
FFMS_DestroyIndex(Index);
|
FFMS_DestroyIndex(Index);
|
||||||
Index = NULL;
|
Index = NULL;
|
||||||
if (VideoSource == NULL) {
|
if (VideoSource == NULL) {
|
||||||
ErrorMsg.Append(wxString::Format(_T("Failed to open video track: %s"), ErrInfo.Buffer));
|
throw VideoOpenError(std::string("Failed to open video track: ") + ErrInfo.Buffer);
|
||||||
throw ErrorMsg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// load video properties
|
// load video properties
|
||||||
|
@ -223,24 +215,22 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
|
|
||||||
const FFMS_Frame *TempFrame = FFMS_GetFrame(VideoSource, 0, &ErrInfo);
|
const FFMS_Frame *TempFrame = FFMS_GetFrame(VideoSource, 0, &ErrInfo);
|
||||||
if (TempFrame == NULL) {
|
if (TempFrame == NULL) {
|
||||||
ErrorMsg.Append(wxString::Format(_T("Failed to decode first frame: %s"), ErrInfo.Buffer));
|
throw VideoOpenError(std::string("Failed to decode first frame: ") + ErrInfo.Buffer);
|
||||||
throw ErrorMsg;
|
|
||||||
}
|
}
|
||||||
Width = TempFrame->EncodedWidth;
|
Width = TempFrame->EncodedWidth;
|
||||||
Height = TempFrame->EncodedHeight;
|
Height = TempFrame->EncodedHeight;
|
||||||
|
|
||||||
if (FFMS_SetOutputFormatV(VideoSource, 1LL << FFMS_GetPixFmt("bgra"), Width, Height, FFMS_RESIZER_BICUBIC, &ErrInfo)) {
|
if (FFMS_SetOutputFormatV(VideoSource, 1LL << FFMS_GetPixFmt("bgra"), Width, Height, FFMS_RESIZER_BICUBIC, &ErrInfo)) {
|
||||||
ErrorMsg.Append(wxString::Format(_T("Failed to set output format: %s"), ErrInfo.Buffer));
|
throw VideoOpenError(std::string("Failed to set output format: ") + ErrInfo.Buffer);
|
||||||
throw ErrorMsg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get frame info data
|
// get frame info data
|
||||||
FFMS_Track *FrameData = FFMS_GetTrackFromVideo(VideoSource);
|
FFMS_Track *FrameData = FFMS_GetTrackFromVideo(VideoSource);
|
||||||
if (FrameData == NULL)
|
if (FrameData == NULL)
|
||||||
throw _T("FFmpegSource video provider: failed to get frame data");
|
throw VideoOpenError("failed to get frame data");
|
||||||
const FFMS_TrackTimeBase *TimeBase = FFMS_GetTimeBase(FrameData);
|
const FFMS_TrackTimeBase *TimeBase = FFMS_GetTimeBase(FrameData);
|
||||||
if (TimeBase == NULL)
|
if (TimeBase == NULL)
|
||||||
throw _T("FFmpegSource video provider: failed to get track time base");
|
throw VideoOpenError("failed to get track time base");
|
||||||
|
|
||||||
const FFMS_FrameInfo *CurFrameData;
|
const FFMS_FrameInfo *CurFrameData;
|
||||||
|
|
||||||
|
@ -249,8 +239,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
for (int CurFrameNum = 0; CurFrameNum < VideoInfo->NumFrames; CurFrameNum++) {
|
for (int CurFrameNum = 0; CurFrameNum < VideoInfo->NumFrames; CurFrameNum++) {
|
||||||
CurFrameData = FFMS_GetFrameInfo(FrameData, CurFrameNum);
|
CurFrameData = FFMS_GetFrameInfo(FrameData, CurFrameNum);
|
||||||
if (CurFrameData == NULL) {
|
if (CurFrameData == NULL) {
|
||||||
ErrorMsg.Append(wxString::Format(_T("Couldn't get info about frame %d"), CurFrameNum));
|
throw VideoOpenError(STD_STR(wxString::Format(L"Couldn't get info about frame %d", CurFrameNum)));
|
||||||
throw ErrorMsg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// keyframe?
|
// keyframe?
|
||||||
|
@ -269,13 +258,11 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||||
/// @brief Close video
|
/// @brief Close video
|
||||||
///
|
///
|
||||||
void FFmpegSourceVideoProvider::Close() {
|
void FFmpegSourceVideoProvider::Close() {
|
||||||
FFMS_DestroyVideoSource(VideoSource);
|
if (VideoSource) FFMS_DestroyVideoSource(VideoSource);
|
||||||
VideoSource = NULL;
|
#ifdef WIN32
|
||||||
|
if (COMInited)
|
||||||
KeyFramesList.clear();
|
CoUninitialize();
|
||||||
FrameNumber = -1;
|
#endif
|
||||||
Timecodes = agi::vfr::Framerate();
|
|
||||||
CurFrame.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Get frame
|
/// @brief Get frame
|
||||||
|
@ -295,8 +282,7 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n) {
|
||||||
// decode frame
|
// decode frame
|
||||||
const FFMS_Frame *SrcFrame = FFMS_GetFrame(VideoSource, n, &ErrInfo);
|
const FFMS_Frame *SrcFrame = FFMS_GetFrame(VideoSource, n, &ErrInfo);
|
||||||
if (SrcFrame == NULL) {
|
if (SrcFrame == NULL) {
|
||||||
ErrorMsg.Append(wxString::Format(_T("Failed to retrieve frame: %s"), ErrInfo.Buffer));
|
throw VideoDecodeError(std::string("Failed to retrieve frame:") + ErrInfo.Buffer);
|
||||||
throw ErrorMsg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CurFrame.SetTo(SrcFrame->Data, Width, Height, SrcFrame->Linesize, FORMAT_RGB32);
|
CurFrame.SetTo(SrcFrame->Data, Width, Height, SrcFrame->Linesize, FORMAT_RGB32);
|
||||||
|
|
|
@ -61,7 +61,6 @@ private:
|
||||||
|
|
||||||
char FFMSErrMsg[1024]; /// FFMS error message
|
char FFMSErrMsg[1024]; /// FFMS error message
|
||||||
FFMS_ErrorInfo ErrInfo; /// FFMS error codes/messages
|
FFMS_ErrorInfo ErrInfo; /// FFMS error codes/messages
|
||||||
wxString ErrorMsg; /// wx-ified error message
|
|
||||||
|
|
||||||
void LoadVideo(wxString filename);
|
void LoadVideo(wxString filename);
|
||||||
void Close();
|
void Close();
|
||||||
|
|
|
@ -58,53 +58,51 @@
|
||||||
/// @return
|
/// @return
|
||||||
///
|
///
|
||||||
VideoProvider *VideoProviderFactory::GetProvider(wxString video) {
|
VideoProvider *VideoProviderFactory::GetProvider(wxString video) {
|
||||||
// First check special case of dummy video
|
|
||||||
if (video.StartsWith(_T("?dummy:"))) {
|
|
||||||
return new DummyVideoProvider(video.wc_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
VideoProvider *y4m_provider = new YUV4MPEGVideoProvider(video);
|
|
||||||
if (y4m_provider)
|
|
||||||
y4m_provider = new VideoProviderCache(y4m_provider);
|
|
||||||
return y4m_provider;
|
|
||||||
}
|
|
||||||
catch (wxString temp) {
|
|
||||||
LOG_E("manager/video/provider/yuv4mpeg") << "Provider creation failed with reason: "<< temp.c_str() << " trying other providers";
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
LOG_E("manager/video/provider/yuv4mpeg") << "Provider creation failed (unknown reason) trying other providers";
|
|
||||||
}
|
|
||||||
|
|
||||||
// List of providers
|
|
||||||
std::vector<std::string> list = GetClasses(OPT_GET("Video/Provider")->GetString());
|
std::vector<std::string> list = GetClasses(OPT_GET("Video/Provider")->GetString());
|
||||||
if (video.StartsWith("?dummy")) list.insert(list.begin(), "Dummy");
|
if (video.StartsWith("?dummy")) list.insert(list.begin(), "Dummy");
|
||||||
list.insert(list.begin(), "YUV4MPEG");
|
list.insert(list.begin(), "YUV4MPEG");
|
||||||
|
|
||||||
// None available
|
bool fileFound = false;
|
||||||
if (list.empty()) throw _T("No video providers are available.");
|
bool fileSupported = false;
|
||||||
|
std::string errors;
|
||||||
// Get provider
|
errors.reserve(1024);
|
||||||
wxString error;
|
for (int i = 0; i < (signed)list.size(); ++i) {
|
||||||
for (unsigned int i=0;i<list.size();i++) {
|
|
||||||
try {
|
try {
|
||||||
// Create provider
|
|
||||||
VideoProvider *provider = Create(list[i], video);
|
VideoProvider *provider = Create(list[i], video);
|
||||||
if (provider) {
|
LOG_I("manager/video/provider") << list[i] << ": opened " << STD_STR(video);
|
||||||
// Cache if necessary
|
if (provider->WantsCaching()) {
|
||||||
if (provider->WantsCaching()) {
|
return new VideoProviderCache(provider);
|
||||||
provider = new VideoProviderCache(provider);
|
|
||||||
}
|
|
||||||
return provider;
|
|
||||||
}
|
}
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
catch (agi::FileNotFoundError const&) {
|
||||||
|
std::string err = list[i] + ": " + STD_STR(video) + " not found.";
|
||||||
|
errors += err + "\n";
|
||||||
|
LOG_D("manager/video/provider") << err;
|
||||||
|
// Keep trying other providers as this one may just not be able to
|
||||||
|
// open a valid path
|
||||||
|
}
|
||||||
|
catch (VideoNotSupported const&) {
|
||||||
|
fileFound = true;
|
||||||
|
std::string err = list[i] + ": " + STD_STR(video) + " is not in a supported format.\n";
|
||||||
|
errors += err + "\n";
|
||||||
|
LOG_D("manager/video/provider") << err;
|
||||||
|
}
|
||||||
|
catch (VideoOpenError const& ex) {
|
||||||
|
fileSupported = true;
|
||||||
|
std::string err = list[i] + ": " + ex.GetMessage();
|
||||||
|
errors += err + "\n";
|
||||||
|
LOG_D("manager/video/provider") << err;
|
||||||
}
|
}
|
||||||
catch (wxString err) { error += list[i] + _T(" factory: ") + err + _T("\n"); }
|
|
||||||
catch (const wxChar *err) { error += list[i] + _T(" factory: ") + wxString(err) + _T("\n"); }
|
|
||||||
catch (...) { error += list[i] + _T(" factory: Unknown error\n"); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failed
|
// No provider could open the file
|
||||||
throw error;
|
LOG_E("manager/video/provider") << "Could not open " << STD_STR(video);
|
||||||
|
std::string msg = "Could not open " + STD_STR(video) + ":\n" + errors;
|
||||||
|
|
||||||
|
if (!fileFound) throw agi::FileNotFoundError(STD_STR(video));
|
||||||
|
if (!fileSupported) throw VideoNotSupported(msg);
|
||||||
|
throw VideoOpenError(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Register all providers
|
/// @brief Register all providers
|
||||||
|
@ -120,5 +118,4 @@ void VideoProviderFactory::RegisterProviders() {
|
||||||
Register<YUV4MPEGVideoProvider>("YUV4MPEG", true);
|
Register<YUV4MPEGVideoProvider>("YUV4MPEG", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
template<> VideoProviderFactory::map *FactoryBase<VideoProvider *(*)(wxString)>::classes = NULL;
|
template<> VideoProviderFactory::map *FactoryBase<VideoProvider *(*)(wxString)>::classes = NULL;
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
|
|
||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
#include "video_provider_yuv4mpeg.h"
|
#include "video_provider_yuv4mpeg.h"
|
||||||
|
|
||||||
// All of this cstdio bogus is because of one reason and one reason only:
|
// All of this cstdio bogus is because of one reason and one reason only:
|
||||||
|
@ -49,36 +50,70 @@
|
||||||
#define ftello _ftelli64
|
#define ftello _ftelli64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
/// @param filename The filename to open
|
/// @param filename The filename to open
|
||||||
YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(wxString filename) {
|
YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(wxString fname)
|
||||||
sf = NULL;
|
: sf(NULL)
|
||||||
w = 0;
|
, w (0)
|
||||||
h = 0;
|
, h (0)
|
||||||
cur_fn = -1;
|
, cur_fn(-1)
|
||||||
inited = false;
|
, pixfmt(Y4M_PIXFMT_NONE)
|
||||||
pixfmt = Y4M_PIXFMT_NONE;
|
, imode(Y4M_ILACE_NOTSET)
|
||||||
imode = Y4M_ILACE_NOTSET;
|
, num_frames(-1)
|
||||||
num_frames = -1;
|
{
|
||||||
fps_rat.num = -1;
|
fps_rat.num = -1;
|
||||||
fps_rat.den = 1;
|
fps_rat.den = 1;
|
||||||
seek_table.clear();
|
|
||||||
|
|
||||||
errmsg = _T("YUV4MPEG video provider: ");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
LoadVideo(filename);
|
wxString filename = wxFileName(fname).GetShortPath();
|
||||||
}
|
|
||||||
catch (wxString temp) {
|
#ifdef WIN32
|
||||||
Close();
|
sf = _wfopen(filename.wc_str(), _T("rb"));
|
||||||
errmsg.Append(temp);
|
#else
|
||||||
throw errmsg;
|
sf = fopen(filename.utf8_str(), "rb");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (sf == NULL) throw agi::FileNotFoundError(STD_STR(fname));
|
||||||
|
|
||||||
|
CheckFileFormat();
|
||||||
|
|
||||||
|
ParseFileHeader(ReadHeader(0, false));
|
||||||
|
|
||||||
|
if (w <= 0 || h <= 0)
|
||||||
|
throw VideoOpenError("Invalid resolution");
|
||||||
|
if (fps_rat.num <= 0 || fps_rat.den <= 0) {
|
||||||
|
fps_rat.num = 25;
|
||||||
|
fps_rat.den = 1;
|
||||||
|
LOG_D("provider/video/yuv4mpeg") << "framerate info unavailable, assuming 25fps";
|
||||||
|
}
|
||||||
|
if (pixfmt == Y4M_PIXFMT_NONE)
|
||||||
|
pixfmt = Y4M_PIXFMT_420JPEG;
|
||||||
|
if (imode == Y4M_ILACE_NOTSET)
|
||||||
|
imode = Y4M_ILACE_UNKNOWN;
|
||||||
|
|
||||||
|
luma_sz = w * h;
|
||||||
|
switch (pixfmt) {
|
||||||
|
case Y4M_PIXFMT_420JPEG:
|
||||||
|
case Y4M_PIXFMT_420MPEG2:
|
||||||
|
case Y4M_PIXFMT_420PALDV:
|
||||||
|
chroma_sz = (w * h) >> 2; break;
|
||||||
|
case Y4M_PIXFMT_422:
|
||||||
|
chroma_sz = (w * h) >> 1; break;
|
||||||
|
/// @todo add support for more pixel formats
|
||||||
|
default:
|
||||||
|
throw VideoOpenError("Unsupported pixel format");
|
||||||
|
}
|
||||||
|
frame_sz = luma_sz + chroma_sz*2;
|
||||||
|
|
||||||
|
num_frames = IndexFile();
|
||||||
|
if (num_frames <= 0 || seek_table.empty())
|
||||||
|
throw VideoOpenError("Unable to determine file length");
|
||||||
|
cur_fn = 0;
|
||||||
|
|
||||||
|
fseeko(sf, 0, SEEK_SET);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
Close();
|
if (sf) fclose(sf);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,88 +121,22 @@ YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(wxString filename) {
|
||||||
|
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
YUV4MPEGVideoProvider::~YUV4MPEGVideoProvider() {
|
YUV4MPEGVideoProvider::~YUV4MPEGVideoProvider() {
|
||||||
Close();
|
if (sf) fclose(sf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Open a video file
|
|
||||||
/// @param _filename The video file to open
|
|
||||||
void YUV4MPEGVideoProvider::LoadVideo(const wxString _filename) {
|
|
||||||
Close();
|
|
||||||
|
|
||||||
wxString filename = wxFileName(_filename).GetShortPath();
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
sf = _wfopen(filename.wc_str(), _T("rb"));
|
|
||||||
#else
|
|
||||||
sf = fopen(filename.utf8_str(), "rb");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (sf == NULL)
|
|
||||||
throw wxString::Format(_T("Failed to open file"));
|
|
||||||
|
|
||||||
CheckFileFormat();
|
|
||||||
|
|
||||||
ParseFileHeader(ReadHeader(0, false));
|
|
||||||
|
|
||||||
if (w <= 0 || h <= 0)
|
|
||||||
throw wxString(_T("Invalid resolution"));
|
|
||||||
if (fps_rat.num <= 0 || fps_rat.den <= 0) {
|
|
||||||
fps_rat.num = 25;
|
|
||||||
fps_rat.den = 1;
|
|
||||||
LOG_D("provider/video/yuv4mpeg") << "framerate info unavailable, assuming 25fps";
|
|
||||||
}
|
|
||||||
if (pixfmt == Y4M_PIXFMT_NONE)
|
|
||||||
pixfmt = Y4M_PIXFMT_420JPEG;
|
|
||||||
if (imode == Y4M_ILACE_NOTSET)
|
|
||||||
imode = Y4M_ILACE_UNKNOWN;
|
|
||||||
|
|
||||||
luma_sz = w * h;
|
|
||||||
switch (pixfmt) {
|
|
||||||
case Y4M_PIXFMT_420JPEG:
|
|
||||||
case Y4M_PIXFMT_420MPEG2:
|
|
||||||
case Y4M_PIXFMT_420PALDV:
|
|
||||||
chroma_sz = (w * h) >> 2; break;
|
|
||||||
case Y4M_PIXFMT_422:
|
|
||||||
chroma_sz = (w * h) >> 1; break;
|
|
||||||
/// @todo add support for more pixel formats
|
|
||||||
default:
|
|
||||||
throw wxString(_T("Unsupported pixel format"));
|
|
||||||
}
|
|
||||||
frame_sz = luma_sz + chroma_sz*2;
|
|
||||||
|
|
||||||
num_frames = IndexFile();
|
|
||||||
if (num_frames <= 0 || seek_table.empty())
|
|
||||||
throw wxString(_T("Unable to determine file length"));
|
|
||||||
cur_fn = 0;
|
|
||||||
|
|
||||||
fseeko(sf, 0, SEEK_SET);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Closes the currently open file (if any) and resets reader state
|
|
||||||
void YUV4MPEGVideoProvider::Close() {
|
|
||||||
seek_table.clear();
|
|
||||||
if (sf)
|
|
||||||
fclose(sf);
|
|
||||||
sf = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Checks if the file is an YUV4MPEG file or not
|
/// @brief Checks if the file is an YUV4MPEG file or not
|
||||||
/// Note that it reports the error by throwing an exception,
|
/// Note that it reports the error by throwing an exception,
|
||||||
/// not by returning a false value.
|
/// not by returning a false value.
|
||||||
void YUV4MPEGVideoProvider::CheckFileFormat() {
|
void YUV4MPEGVideoProvider::CheckFileFormat() {
|
||||||
char buf[10];
|
char buf[10];
|
||||||
if (fread(buf, 10, 1, sf) != 1)
|
if (fread(buf, 10, 1, sf) != 1)
|
||||||
throw wxString(_T("CheckFileFormat: Failed reading header"));
|
throw VideoNotSupported("CheckFileFormat: Failed reading header");
|
||||||
if (strncmp("YUV4MPEG2 ", buf, 10))
|
if (strncmp("YUV4MPEG2 ", buf, 10))
|
||||||
throw wxString(_T("CheckFileFormat: File is not a YUV4MPEG file (bad magic)"));
|
throw VideoNotSupported("CheckFileFormat: File is not a YUV4MPEG file (bad magic)");
|
||||||
|
|
||||||
fseeko(sf, 0, SEEK_SET);
|
fseeko(sf, 0, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Read a frame or file header at a given file position
|
/// @brief Read a frame or file header at a given file position
|
||||||
/// @param startpos The byte offset at where to start reading
|
/// @param startpos The byte offset at where to start reading
|
||||||
/// @param reset_pos If true, the function will reset the file position to what it was before the function call before returning
|
/// @param reset_pos If true, the function will reset the file position to what it was before the function call before returning
|
||||||
|
@ -175,17 +144,17 @@ void YUV4MPEGVideoProvider::CheckFileFormat() {
|
||||||
std::vector<wxString> YUV4MPEGVideoProvider::ReadHeader(int64_t startpos, bool reset_pos) {
|
std::vector<wxString> YUV4MPEGVideoProvider::ReadHeader(int64_t startpos, bool reset_pos) {
|
||||||
int64_t oldpos = ftello(sf);
|
int64_t oldpos = ftello(sf);
|
||||||
std::vector<wxString> tags;
|
std::vector<wxString> tags;
|
||||||
wxString curtag = _T("");
|
wxString curtag;
|
||||||
int bytesread = 0;
|
int bytesread = 0;
|
||||||
int buf;
|
int buf;
|
||||||
|
|
||||||
if (fseeko(sf, startpos, SEEK_SET))
|
if (fseeko(sf, startpos, SEEK_SET))
|
||||||
throw wxString::Format(_T("YUV4MPEG video provider: ReadHeader: failed seeking to position %d"), startpos);
|
throw VideoOpenError(STD_STR(wxString::Format(L"YUV4MPEG video provider: ReadHeader: failed seeking to position %d", startpos)));
|
||||||
|
|
||||||
// read header until terminating newline (0x0A) is found
|
// read header until terminating newline (0x0A) is found
|
||||||
while ((buf = fgetc(sf)) != 0x0A) {
|
while ((buf = fgetc(sf)) != 0x0A) {
|
||||||
if (ferror(sf))
|
if (ferror(sf))
|
||||||
throw wxString(_T("ReadHeader: Failed to read from file"));
|
throw VideoOpenError("ReadHeader: Failed to read from file");
|
||||||
if (feof(sf)) {
|
if (feof(sf)) {
|
||||||
// you know, this is one of the places where it would be really nice
|
// you know, this is one of the places where it would be really nice
|
||||||
// to be able to throw an exception object that tells the caller that EOF was reached
|
// to be able to throw an exception object that tells the caller that EOF was reached
|
||||||
|
@ -195,9 +164,9 @@ std::vector<wxString> YUV4MPEGVideoProvider::ReadHeader(int64_t startpos, bool r
|
||||||
|
|
||||||
// some basic low-effort sanity checking
|
// some basic low-effort sanity checking
|
||||||
if (buf == 0x00)
|
if (buf == 0x00)
|
||||||
throw wxString(_T("ReadHeader: Malformed header (unexpected NUL)"));
|
throw VideoOpenError("ReadHeader: Malformed header (unexpected NUL)");
|
||||||
if (++bytesread >= YUV4MPEG_HEADER_MAXLEN)
|
if (++bytesread >= YUV4MPEG_HEADER_MAXLEN)
|
||||||
throw wxString(_T("ReadHeader: Malformed header (no terminating newline found)"));
|
throw VideoOpenError("ReadHeader: Malformed header (no terminating newline found)");
|
||||||
|
|
||||||
// found a new tag
|
// found a new tag
|
||||||
if (buf == 0x20) {
|
if (buf == 0x20) {
|
||||||
|
@ -220,14 +189,13 @@ std::vector<wxString> YUV4MPEGVideoProvider::ReadHeader(int64_t startpos, bool r
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Parses a list of parameters and sets reader state accordingly
|
/// @brief Parses a list of parameters and sets reader state accordingly
|
||||||
/// @param tags The list of parameters to parse
|
/// @param tags The list of parameters to parse
|
||||||
void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
||||||
if (tags.size() <= 1)
|
if (tags.size() <= 1)
|
||||||
throw wxString(_T("ParseFileHeader: contentless header"));
|
throw VideoOpenError("ParseFileHeader: contentless header");
|
||||||
if (tags.front().Cmp(_T("YUV4MPEG2")))
|
if (tags.front().Cmp(_T("YUV4MPEG2")))
|
||||||
throw wxString(_T("ParseFileHeader: malformed header (bad magic)"));
|
throw VideoOpenError("ParseFileHeader: malformed header (bad magic)");
|
||||||
|
|
||||||
// temporary stuff
|
// temporary stuff
|
||||||
int t_w = -1;
|
int t_w = -1;
|
||||||
|
@ -244,17 +212,17 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
||||||
|
|
||||||
if (tags.at(i).StartsWith(_T("W"), &tag)) {
|
if (tags.at(i).StartsWith(_T("W"), &tag)) {
|
||||||
if (!tag.ToLong(&tmp_long1))
|
if (!tag.ToLong(&tmp_long1))
|
||||||
throw wxString(_T("ParseFileHeader: invalid width"));
|
throw VideoOpenError("ParseFileHeader: invalid width");
|
||||||
t_w = (int)tmp_long1;
|
t_w = (int)tmp_long1;
|
||||||
}
|
}
|
||||||
else if (tags.at(i).StartsWith(_T("H"), &tag)) {
|
else if (tags.at(i).StartsWith(_T("H"), &tag)) {
|
||||||
if (!tag.ToLong(&tmp_long1))
|
if (!tag.ToLong(&tmp_long1))
|
||||||
throw wxString(_T("ParseFileHeader: invalid height"));
|
throw VideoOpenError("ParseFileHeader: invalid height");
|
||||||
t_h = (int)tmp_long1;
|
t_h = (int)tmp_long1;
|
||||||
}
|
}
|
||||||
else if (tags.at(i).StartsWith(_T("F"), &tag)) {
|
else if (tags.at(i).StartsWith(_T("F"), &tag)) {
|
||||||
if (!(tag.BeforeFirst(':')).ToLong(&tmp_long1) && tag.AfterFirst(':').ToLong(&tmp_long2))
|
if (!(tag.BeforeFirst(':')).ToLong(&tmp_long1) && tag.AfterFirst(':').ToLong(&tmp_long2))
|
||||||
throw wxString(_T("ParseFileHeader: invalid framerate"));
|
throw VideoOpenError("ParseFileHeader: invalid framerate");
|
||||||
t_fps_num = (int)tmp_long1;
|
t_fps_num = (int)tmp_long1;
|
||||||
t_fps_den = (int)tmp_long2;
|
t_fps_den = (int)tmp_long2;
|
||||||
}
|
}
|
||||||
|
@ -271,7 +239,7 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
||||||
else if (!tag.CmpNoCase(_T("444alpha"))) t_pixfmt = Y4M_PIXFMT_444ALPHA;
|
else if (!tag.CmpNoCase(_T("444alpha"))) t_pixfmt = Y4M_PIXFMT_444ALPHA;
|
||||||
else if (!tag.CmpNoCase(_T("mono"))) t_pixfmt = Y4M_PIXFMT_MONO;
|
else if (!tag.CmpNoCase(_T("mono"))) t_pixfmt = Y4M_PIXFMT_MONO;
|
||||||
else
|
else
|
||||||
throw wxString(_T("ParseFileHeader: invalid or unknown colorspace"));
|
throw VideoOpenError("ParseFileHeader: invalid or unknown colorspace");
|
||||||
}
|
}
|
||||||
else if (tags.at(i).StartsWith(_T("I"), &tag)) {
|
else if (tags.at(i).StartsWith(_T("I"), &tag)) {
|
||||||
if (!tag.CmpNoCase(_T("p"))) t_imode = Y4M_ILACE_PROGRESSIVE;
|
if (!tag.CmpNoCase(_T("p"))) t_imode = Y4M_ILACE_PROGRESSIVE;
|
||||||
|
@ -280,7 +248,7 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
||||||
else if (!tag.CmpNoCase(_T("m"))) t_imode = Y4M_ILACE_MIXED;
|
else if (!tag.CmpNoCase(_T("m"))) t_imode = Y4M_ILACE_MIXED;
|
||||||
else if (!tag.CmpNoCase(_T("?"))) t_imode = Y4M_ILACE_UNKNOWN;
|
else if (!tag.CmpNoCase(_T("?"))) t_imode = Y4M_ILACE_UNKNOWN;
|
||||||
else
|
else
|
||||||
throw wxString(_T("ParseFileHeader: invalid or unknown interlacing mode"));
|
throw VideoOpenError("ParseFileHeader: invalid or unknown interlacing mode");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LOG_D("provider/video/yuv4mpeg") << "Unparsed tag: " << tags.at(i).c_str();
|
LOG_D("provider/video/yuv4mpeg") << "Unparsed tag: " << tags.at(i).c_str();
|
||||||
|
@ -292,15 +260,15 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
||||||
// but the "reference implementation" (mjpegtools) does, so I'm doing it too.
|
// but the "reference implementation" (mjpegtools) does, so I'm doing it too.
|
||||||
if (inited) {
|
if (inited) {
|
||||||
if (t_w > 0 && t_w != w)
|
if (t_w > 0 && t_w != w)
|
||||||
throw wxString(_T("ParseFileHeader: illegal width change"));
|
throw VideoOpenError("ParseFileHeader: illegal width change");
|
||||||
if (t_h > 0 && t_h != h)
|
if (t_h > 0 && t_h != h)
|
||||||
throw wxString(_T("ParseFileHeader: illegal height change"));
|
throw VideoOpenError("ParseFileHeader: illegal height change");
|
||||||
if ((t_fps_num > 0 && t_fps_den > 0) && (t_fps_num != fps_rat.num || t_fps_den != fps_rat.den))
|
if ((t_fps_num > 0 && t_fps_den > 0) && (t_fps_num != fps_rat.num || t_fps_den != fps_rat.den))
|
||||||
throw wxString(_T("ParseFileHeader: illegal framerate change"));
|
throw VideoOpenError("ParseFileHeader: illegal framerate change");
|
||||||
if (t_pixfmt != Y4M_PIXFMT_NONE && t_pixfmt != pixfmt)
|
if (t_pixfmt != Y4M_PIXFMT_NONE && t_pixfmt != pixfmt)
|
||||||
throw wxString(_T("ParseFileHeader: illegal colorspace change"));
|
throw VideoOpenError("ParseFileHeader: illegal colorspace change");
|
||||||
if (t_imode != Y4M_ILACE_NOTSET && t_imode != imode)
|
if (t_imode != Y4M_ILACE_NOTSET && t_imode != imode)
|
||||||
throw wxString(_T("ParseFileHeader: illegal interlacing mode change"));
|
throw VideoOpenError("ParseFileHeader: illegal interlacing mode change");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
w = t_w;
|
w = t_w;
|
||||||
|
@ -314,21 +282,19 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Parses a frame header
|
/// @brief Parses a frame header
|
||||||
/// @param tags The list of parameters to parse
|
/// @param tags The list of parameters to parse
|
||||||
/// @return The flags set, as a binary mask
|
/// @return The flags set, as a binary mask
|
||||||
/// This function is currently unimplemented (it will always return Y4M_FFLAG_NONE).
|
/// This function is currently unimplemented (it will always return Y4M_FFLAG_NONE).
|
||||||
YUV4MPEGVideoProvider::Y4M_FrameFlags YUV4MPEGVideoProvider::ParseFrameHeader(const std::vector<wxString>& tags) {
|
YUV4MPEGVideoProvider::Y4M_FrameFlags YUV4MPEGVideoProvider::ParseFrameHeader(const std::vector<wxString>& tags) {
|
||||||
if (tags.front().Cmp(_("FRAME")))
|
if (tags.front().Cmp(_("FRAME")))
|
||||||
throw wxString(_T("ParseFrameHeader: malformed frame header (bad magic)"));
|
throw VideoOpenError("ParseFrameHeader: malformed frame header (bad magic)");
|
||||||
|
|
||||||
/// @todo implement parsing of frame flags
|
/// @todo implement parsing of frame flags
|
||||||
|
|
||||||
return Y4M_FFLAG_NONE;
|
return Y4M_FFLAG_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Indexes the file
|
/// @brief Indexes the file
|
||||||
/// @return The number of frames found in the file
|
/// @return The number of frames found in the file
|
||||||
/// This function goes through the file, finds and parses all file and frame headers,
|
/// This function goes through the file, finds and parses all file and frame headers,
|
||||||
|
@ -362,7 +328,7 @@ int YUV4MPEGVideoProvider::IndexFile() {
|
||||||
seek_table.push_back(curpos);
|
seek_table.push_back(curpos);
|
||||||
// seek to next frame header start position
|
// seek to next frame header start position
|
||||||
if (fseeko(sf, frame_sz, SEEK_CUR))
|
if (fseeko(sf, frame_sz, SEEK_CUR))
|
||||||
throw wxString::Format(_T("IndexFile: failed seeking to position %d"), curpos + frame_sz);
|
throw VideoOpenError(STD_STR(wxString::Format(_T("IndexFile: failed seeking to position %d"), curpos + frame_sz)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/// @todo implement rff flags etc
|
/// @todo implement rff flags etc
|
||||||
|
@ -372,8 +338,6 @@ int YUV4MPEGVideoProvider::IndexFile() {
|
||||||
return framecount;
|
return framecount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Gets a given frame
|
/// @brief Gets a given frame
|
||||||
/// @param n The frame number to return
|
/// @param n The frame number to return
|
||||||
/// @return The video frame
|
/// @return The video frame
|
||||||
|
@ -398,7 +362,7 @@ const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n) {
|
||||||
src_fmt = FORMAT_YUY2; uv_width = w / 2; break;
|
src_fmt = FORMAT_YUY2; uv_width = w / 2; break;
|
||||||
/// @todo add support for more pixel formats
|
/// @todo add support for more pixel formats
|
||||||
default:
|
default:
|
||||||
throw wxString(_T("YUV4MPEG video provider: GetFrame: Unsupported source colorspace"));
|
throw _T("YUV4MPEG video provider: GetFrame: Unsupported source colorspace");
|
||||||
}
|
}
|
||||||
|
|
||||||
AegiVideoFrame tmp_frame;
|
AegiVideoFrame tmp_frame;
|
||||||
|
@ -416,11 +380,11 @@ const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n) {
|
||||||
size_t ret;
|
size_t ret;
|
||||||
ret = fread(tmp_frame.data[0], luma_sz, 1, sf);
|
ret = fread(tmp_frame.data[0], luma_sz, 1, sf);
|
||||||
if (ret != 1 || feof(sf) || ferror(sf))
|
if (ret != 1 || feof(sf) || ferror(sf))
|
||||||
throw wxString(_T("YUV4MPEG video provider: GetFrame: failed to read luma plane"));
|
throw _T("YUV4MPEG video provider: GetFrame: failed to read luma plane");
|
||||||
for (int i = 1; i <= 2; i++) {
|
for (int i = 1; i <= 2; i++) {
|
||||||
ret = fread(tmp_frame.data[i], chroma_sz, 1, sf);
|
ret = fread(tmp_frame.data[i], chroma_sz, 1, sf);
|
||||||
if (ret != 1 || feof(sf) || ferror(sf))
|
if (ret != 1 || feof(sf) || ferror(sf))
|
||||||
throw wxString(_T("YUV4MPEG video provider: GetFrame: failed to read chroma planes"));
|
throw _T("YUV4MPEG video provider: GetFrame: failed to read chroma planes");
|
||||||
}
|
}
|
||||||
|
|
||||||
AegiVideoFrame dst_frame;
|
AegiVideoFrame dst_frame;
|
||||||
|
|
|
@ -131,11 +131,6 @@ class YUV4MPEGVideoProvider : public VideoProvider {
|
||||||
/// each frame header can be found
|
/// each frame header can be found
|
||||||
std::vector<int64_t> seek_table;
|
std::vector<int64_t> seek_table;
|
||||||
|
|
||||||
wxString errmsg; /// error message
|
|
||||||
|
|
||||||
void LoadVideo(const wxString filename);
|
|
||||||
void Close();
|
|
||||||
|
|
||||||
void CheckFileFormat();
|
void CheckFileFormat();
|
||||||
void ParseFileHeader(const std::vector<wxString>& tags);
|
void ParseFileHeader(const std::vector<wxString>& tags);
|
||||||
Y4M_FrameFlags ParseFrameHeader(const std::vector<wxString>& tags);
|
Y4M_FrameFlags ParseFrameHeader(const std::vector<wxString>& tags);
|
||||||
|
|
|
@ -40,12 +40,6 @@
|
||||||
#include <wx/glcanvas.h>
|
#include <wx/glcanvas.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include <OpenGL/GL.h>
|
|
||||||
#else
|
|
||||||
#include <GL/gl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "ass_dialogue.h"
|
#include "ass_dialogue.h"
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "ass_override.h"
|
#include "ass_override.h"
|
||||||
|
|
|
@ -37,12 +37,8 @@
|
||||||
#include <wx/toolbar.h>
|
#include <wx/toolbar.h>
|
||||||
|
|
||||||
#ifdef HAVE_APPLE_OPENGL_FRAMEWORK
|
#ifdef HAVE_APPLE_OPENGL_FRAMEWORK
|
||||||
#include <OpenGL/GL.h>
|
|
||||||
#include <OpenGL/glu.h>
|
|
||||||
#include <OpenGL/glext.h>
|
#include <OpenGL/glext.h>
|
||||||
#else
|
#else
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <GL/glu.h>
|
|
||||||
#include "gl/glext.h"
|
#include "gl/glext.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue