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:
Thomas Goyne 2010-08-02 06:32:01 +00:00
parent 71fb04cd29
commit c10e9e3a5b
65 changed files with 574 additions and 1279 deletions

View file

@ -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
}; };

View file

@ -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

View file

@ -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

View file

@ -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.
}; };

View file

@ -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());
} }

View file

@ -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) {

View file

@ -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; }

View file

@ -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);
} }

View file

@ -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()

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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>
} }

View file

@ -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;

View file

@ -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() {

View file

@ -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

View file

@ -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);

View file

@ -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;
} }

View file

@ -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(); }
}; };

View file

@ -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;
} }

View file

@ -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; }

View file

@ -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;
} }
} }

View file

@ -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);
}; };

View file

@ -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 */

View file

@ -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);
}; };

View file

@ -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"";
} }

View file

@ -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);

View file

@ -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;
} }

View file

@ -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) {
} }
} }
} }

View file

@ -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;

View file

@ -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

View file

@ -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 {

View file

@ -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

View file

@ -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); }

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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");

View file

@ -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");

View file

@ -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) {
} }
} }

View file

@ -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;
}; };

View file

@ -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
/// ///

View file

@ -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

View file

@ -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>

View file

@ -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);
} }

View file

@ -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 {

View file

@ -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"

View file

@ -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);
} }
} }

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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(); }
}; };

View file

@ -122,12 +122,12 @@ DummyVideoProvider::DummyVideoProvider(wxString filename)
{ {
wxString params; wxString params;
if (!filename.StartsWith(_T("?dummy:"), &params)) { if (!filename.StartsWith(_T("?dummy:"), &params)) {
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();

View file

@ -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);

View file

@ -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();

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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"

View file

@ -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