Common: Add ProgressCallback class
This commit is contained in:
parent
8f39a0f154
commit
8028b7b4a3
|
@ -41,6 +41,8 @@ add_library(common
|
|||
null_audio_stream.cpp
|
||||
null_audio_stream.h
|
||||
rectangle.h
|
||||
progress_callback.cpp
|
||||
progress_callback.h
|
||||
state_wrapper.cpp
|
||||
state_wrapper.h
|
||||
string.cpp
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
<ClInclude Include="log.h" />
|
||||
<ClInclude Include="md5_digest.h" />
|
||||
<ClInclude Include="null_audio_stream.h" />
|
||||
<ClInclude Include="progress_callback.h" />
|
||||
<ClInclude Include="rectangle.h" />
|
||||
<ClInclude Include="cd_subchannel_replacement.h" />
|
||||
<ClInclude Include="state_wrapper.h" />
|
||||
|
@ -94,6 +95,7 @@
|
|||
<ClCompile Include="log.cpp" />
|
||||
<ClCompile Include="md5_digest.cpp" />
|
||||
<ClCompile Include="null_audio_stream.cpp" />
|
||||
<ClCompile Include="progress_callback.cpp" />
|
||||
<ClCompile Include="state_wrapper.cpp" />
|
||||
<ClCompile Include="cd_xa.cpp" />
|
||||
<ClCompile Include="string.cpp" />
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
<Filter>d3d11</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="hash_combine.h" />
|
||||
<ClInclude Include="progress_callback.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="jit_code_buffer.cpp" />
|
||||
|
@ -98,6 +99,7 @@
|
|||
<Filter>d3d11</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cd_image_chd.cpp" />
|
||||
<ClCompile Include="progress_callback.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="bitfield.natvis" />
|
||||
|
|
|
@ -0,0 +1,397 @@
|
|||
#include "progress_callback.h"
|
||||
#include "assert.h"
|
||||
#include "byte_stream.h"
|
||||
#include "log.h"
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
Log_SetChannel(ProgressCallback);
|
||||
|
||||
ProgressCallback::~ProgressCallback() {}
|
||||
|
||||
void ProgressCallback::SetFormattedStatusText(const char* Format, ...)
|
||||
{
|
||||
SmallString str;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, Format);
|
||||
str.FormatVA(Format, ap);
|
||||
va_end(ap);
|
||||
|
||||
SetStatusText(str);
|
||||
}
|
||||
|
||||
void ProgressCallback::DisplayFormattedError(const char* format, ...)
|
||||
{
|
||||
SmallString str;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
str.FormatVA(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
DisplayError(str);
|
||||
}
|
||||
|
||||
void ProgressCallback::DisplayFormattedWarning(const char* format, ...)
|
||||
{
|
||||
SmallString str;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
str.FormatVA(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
DisplayWarning(str);
|
||||
}
|
||||
|
||||
void ProgressCallback::DisplayFormattedInformation(const char* format, ...)
|
||||
{
|
||||
SmallString str;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
str.FormatVA(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
DisplayInformation(str);
|
||||
}
|
||||
|
||||
void ProgressCallback::DisplayFormattedDebugMessage(const char* format, ...)
|
||||
{
|
||||
SmallString str;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
str.FormatVA(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
DisplayDebugMessage(str);
|
||||
}
|
||||
|
||||
void ProgressCallback::DisplayFormattedModalError(const char* format, ...)
|
||||
{
|
||||
SmallString str;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
str.FormatVA(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
ModalError(str);
|
||||
}
|
||||
|
||||
bool ProgressCallback::DisplayFormattedModalConfirmation(const char* format, ...)
|
||||
{
|
||||
SmallString str;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
str.FormatVA(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ModalConfirmation(str);
|
||||
}
|
||||
|
||||
void ProgressCallback::UpdateProgressFromStream(ByteStream* pStream)
|
||||
{
|
||||
u32 streamSize = (u32)pStream->GetSize();
|
||||
u32 streamPosition = (u32)pStream->GetPosition();
|
||||
|
||||
SetProgressRange(streamSize);
|
||||
SetProgressValue(streamPosition);
|
||||
}
|
||||
|
||||
class NullProgressCallbacks final : public ProgressCallback
|
||||
{
|
||||
public:
|
||||
void PushState() override {}
|
||||
void PopState() override {}
|
||||
|
||||
bool IsCancelled() const override { return false; }
|
||||
bool IsCancellable() const override { return false; }
|
||||
|
||||
void SetCancellable(bool cancellable) override {}
|
||||
void SetStatusText(const char* statusText) override {}
|
||||
void SetProgressRange(u32 range) override {}
|
||||
void SetProgressValue(u32 value) override {}
|
||||
void IncrementProgressValue() override {}
|
||||
|
||||
void DisplayError(const char* message) override { Log_ErrorPrint(message); }
|
||||
void DisplayWarning(const char* message) override { Log_WarningPrint(message); }
|
||||
void DisplayInformation(const char* message) override { Log_InfoPrint(message); }
|
||||
void DisplayDebugMessage(const char* message) override { Log_DevPrint(message); }
|
||||
|
||||
void ModalError(const char* message) override { Log_ErrorPrint(message); }
|
||||
bool ModalConfirmation(const char* message) override
|
||||
{
|
||||
Log_InfoPrint(message);
|
||||
return false;
|
||||
}
|
||||
u32 ModalPrompt(const char* message, u32 nOptions, ...) override
|
||||
{
|
||||
DebugAssert(nOptions > 0);
|
||||
Log_InfoPrint(message);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
static NullProgressCallbacks s_nullProgressCallbacks;
|
||||
ProgressCallback* ProgressCallback::NullProgressCallback = &s_nullProgressCallbacks;
|
||||
|
||||
BaseProgressCallback::BaseProgressCallback()
|
||||
: m_cancellable(false), m_cancelled(false), m_progress_range(1), m_progress_value(0), m_base_progress_value(0),
|
||||
m_saved_state(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
BaseProgressCallback::~BaseProgressCallback()
|
||||
{
|
||||
State* pNextState = m_saved_state;
|
||||
while (pNextState != NULL)
|
||||
{
|
||||
State* pCurrentState = pNextState;
|
||||
pNextState = pCurrentState->next_saved_state;
|
||||
delete pCurrentState;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseProgressCallback::PushState()
|
||||
{
|
||||
State* pNewState = new State;
|
||||
pNewState->cancellable = m_cancellable;
|
||||
pNewState->status_text = m_status_text;
|
||||
pNewState->progress_range = m_progress_range;
|
||||
pNewState->progress_value = m_progress_value;
|
||||
pNewState->base_progress_value = m_base_progress_value;
|
||||
pNewState->next_saved_state = m_saved_state;
|
||||
m_saved_state = pNewState;
|
||||
}
|
||||
|
||||
void BaseProgressCallback::PopState()
|
||||
{
|
||||
DebugAssert(m_saved_state);
|
||||
State* state = m_saved_state;
|
||||
m_saved_state = nullptr;
|
||||
|
||||
// impose the current position into the previous range
|
||||
const u32 new_progress_value =
|
||||
(m_progress_range != 0) ?
|
||||
static_cast<u32>(((float)m_progress_value / (float)m_progress_range) * (float)state->progress_range) :
|
||||
state->progress_value;
|
||||
|
||||
SetCancellable(state->cancellable);
|
||||
SetStatusText(state->status_text);
|
||||
SetProgressRange(state->progress_range);
|
||||
SetProgressValue(new_progress_value);
|
||||
|
||||
m_base_progress_value = state->base_progress_value;
|
||||
m_saved_state = state->next_saved_state;
|
||||
delete state;
|
||||
}
|
||||
|
||||
bool BaseProgressCallback::IsCancelled() const
|
||||
{
|
||||
return m_cancelled;
|
||||
}
|
||||
|
||||
bool BaseProgressCallback::IsCancellable() const
|
||||
{
|
||||
return m_cancellable;
|
||||
}
|
||||
|
||||
void BaseProgressCallback::SetCancellable(bool cancellable)
|
||||
{
|
||||
m_cancellable = cancellable;
|
||||
}
|
||||
|
||||
void BaseProgressCallback::SetStatusText(const char* text)
|
||||
{
|
||||
m_status_text = text;
|
||||
}
|
||||
|
||||
void BaseProgressCallback::SetProgressRange(u32 range)
|
||||
{
|
||||
if (m_saved_state)
|
||||
{
|
||||
// impose the previous range on this range
|
||||
m_progress_range = m_saved_state->progress_range * range;
|
||||
m_base_progress_value = m_progress_value = m_saved_state->progress_value * range;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_progress_range = range;
|
||||
m_progress_value = 0;
|
||||
m_base_progress_value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseProgressCallback::SetProgressValue(u32 value)
|
||||
{
|
||||
m_progress_value = m_base_progress_value + value;
|
||||
}
|
||||
|
||||
void BaseProgressCallback::IncrementProgressValue()
|
||||
{
|
||||
SetProgressValue((m_progress_value - m_base_progress_value) + 1);
|
||||
}
|
||||
|
||||
ConsoleProgressCallback::ConsoleProgressCallback()
|
||||
: BaseProgressCallback(), m_last_percent_complete(std::numeric_limits<float>::infinity()),
|
||||
m_last_bar_length(0xFFFFFFFF)
|
||||
{
|
||||
}
|
||||
|
||||
ConsoleProgressCallback::~ConsoleProgressCallback()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::PushState()
|
||||
{
|
||||
BaseProgressCallback::PushState();
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::PopState()
|
||||
{
|
||||
BaseProgressCallback::PopState();
|
||||
Redraw(false);
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::SetCancellable(bool cancellable)
|
||||
{
|
||||
BaseProgressCallback::SetCancellable(cancellable);
|
||||
Redraw(false);
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::SetStatusText(const char* text)
|
||||
{
|
||||
BaseProgressCallback::SetStatusText(text);
|
||||
Redraw(false);
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::SetProgressRange(u32 range)
|
||||
{
|
||||
u32 last_range = m_progress_range;
|
||||
|
||||
BaseProgressCallback::SetProgressRange(range);
|
||||
|
||||
if (m_progress_range != last_range)
|
||||
Redraw(false);
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::SetProgressValue(u32 value)
|
||||
{
|
||||
u32 lastValue = m_progress_value;
|
||||
|
||||
BaseProgressCallback::SetProgressValue(value);
|
||||
|
||||
if (m_progress_value != lastValue)
|
||||
Redraw(true);
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::Clear()
|
||||
{
|
||||
SmallString message;
|
||||
for (u32 i = 0; i < COLUMNS; i++)
|
||||
message.AppendCharacter(' ');
|
||||
message.AppendCharacter('\r');
|
||||
|
||||
std::fwrite(message.GetCharArray(), message.GetLength(), 1, stderr);
|
||||
std::fflush(stderr);
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::Redraw(bool update_value_only)
|
||||
{
|
||||
float percent_complete = (m_progress_range > 0) ? ((float)m_progress_value / (float)m_progress_range) * 100.0f : 0.0f;
|
||||
if (percent_complete > 100.0f)
|
||||
percent_complete = 100.0f;
|
||||
|
||||
const u32 current_length = m_status_text.GetLength() + 14;
|
||||
const u32 max_bar_length = (current_length < COLUMNS) ? COLUMNS - current_length : 0;
|
||||
const u32 current_bar_length =
|
||||
(max_bar_length > 0) ? (static_cast<u32>(percent_complete / 100.0f * (float)max_bar_length)) : 0;
|
||||
|
||||
if (update_value_only && (current_bar_length == m_last_bar_length) &&
|
||||
std::abs(percent_complete - m_last_percent_complete) < 0.01f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_last_bar_length = current_bar_length;
|
||||
m_last_percent_complete = percent_complete;
|
||||
|
||||
SmallString message;
|
||||
message.AppendString(m_status_text);
|
||||
message.AppendFormattedString(" [%.2f%%]", percent_complete);
|
||||
|
||||
if (max_bar_length > 0)
|
||||
{
|
||||
message.AppendString(" |");
|
||||
|
||||
u32 i;
|
||||
for (i = 0; i < current_bar_length; i++)
|
||||
message.AppendCharacter('=');
|
||||
for (; i < max_bar_length; i++)
|
||||
message.AppendCharacter(' ');
|
||||
|
||||
message.AppendString("|");
|
||||
}
|
||||
|
||||
message.AppendCharacter('\r');
|
||||
|
||||
std::fwrite(message.GetCharArray(), message.GetLength(), 1, stderr);
|
||||
std::fflush(stderr);
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::DisplayError(const char* message)
|
||||
{
|
||||
Clear();
|
||||
Log_ErrorPrint(message);
|
||||
Redraw(false);
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::DisplayWarning(const char* message)
|
||||
{
|
||||
Clear();
|
||||
Log_WarningPrint(message);
|
||||
Redraw(false);
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::DisplayInformation(const char* message)
|
||||
{
|
||||
Clear();
|
||||
Log_InfoPrint(message);
|
||||
Redraw(false);
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::DisplayDebugMessage(const char* message)
|
||||
{
|
||||
Clear();
|
||||
Log_DevPrint(message);
|
||||
Redraw(false);
|
||||
}
|
||||
|
||||
void ConsoleProgressCallback::ModalError(const char* message)
|
||||
{
|
||||
Clear();
|
||||
Log_ErrorPrint(message);
|
||||
Redraw(false);
|
||||
}
|
||||
|
||||
bool ConsoleProgressCallback::ModalConfirmation(const char* message)
|
||||
{
|
||||
Clear();
|
||||
Log_InfoPrint(message);
|
||||
Redraw(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 ConsoleProgressCallback::ModalPrompt(const char* message, u32 num_options, ...)
|
||||
{
|
||||
Clear();
|
||||
DebugAssert(num_options > 0);
|
||||
Log_InfoPrint(message);
|
||||
Redraw(false);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
#pragma once
|
||||
#include "string.h"
|
||||
#include "types.h"
|
||||
|
||||
class ByteStream;
|
||||
|
||||
class ProgressCallback
|
||||
{
|
||||
public:
|
||||
virtual ~ProgressCallback();
|
||||
|
||||
virtual void PushState() = 0;
|
||||
virtual void PopState() = 0;
|
||||
|
||||
virtual bool IsCancelled() const = 0;
|
||||
virtual bool IsCancellable() const = 0;
|
||||
|
||||
virtual void SetCancellable(bool cancellable) = 0;
|
||||
|
||||
virtual void SetStatusText(const char* text) = 0;
|
||||
virtual void SetProgressRange(u32 range) = 0;
|
||||
virtual void SetProgressValue(u32 value) = 0;
|
||||
virtual void IncrementProgressValue() = 0;
|
||||
|
||||
void SetFormattedStatusText(const char* Format, ...);
|
||||
|
||||
virtual void DisplayError(const char* message) = 0;
|
||||
virtual void DisplayWarning(const char* message) = 0;
|
||||
virtual void DisplayInformation(const char* message) = 0;
|
||||
virtual void DisplayDebugMessage(const char* message) = 0;
|
||||
|
||||
virtual void ModalError(const char* message) = 0;
|
||||
virtual bool ModalConfirmation(const char* message) = 0;
|
||||
virtual u32 ModalPrompt(const char* message, u32 num_options, ...) = 0;
|
||||
|
||||
void DisplayFormattedError(const char* format, ...);
|
||||
void DisplayFormattedWarning(const char* format, ...);
|
||||
void DisplayFormattedInformation(const char* format, ...);
|
||||
void DisplayFormattedDebugMessage(const char* format, ...);
|
||||
void DisplayFormattedModalError(const char* format, ...);
|
||||
bool DisplayFormattedModalConfirmation(const char* format, ...);
|
||||
|
||||
void UpdateProgressFromStream(ByteStream* stream);
|
||||
|
||||
public:
|
||||
static ProgressCallback* NullProgressCallback;
|
||||
};
|
||||
|
||||
class BaseProgressCallback : public ProgressCallback
|
||||
{
|
||||
public:
|
||||
BaseProgressCallback();
|
||||
virtual ~BaseProgressCallback();
|
||||
|
||||
virtual void PushState() override;
|
||||
virtual void PopState() override;
|
||||
|
||||
virtual bool IsCancelled() const override;
|
||||
virtual bool IsCancellable() const override;
|
||||
|
||||
virtual void SetCancellable(bool cancellable) override;
|
||||
virtual void SetStatusText(const char* text) override;
|
||||
virtual void SetProgressRange(u32 range) override;
|
||||
virtual void SetProgressValue(u32 value) override;
|
||||
virtual void IncrementProgressValue() override;
|
||||
|
||||
protected:
|
||||
struct State
|
||||
{
|
||||
State* next_saved_state;
|
||||
String status_text;
|
||||
u32 progress_range;
|
||||
u32 progress_value;
|
||||
u32 base_progress_value;
|
||||
bool cancellable;
|
||||
};
|
||||
|
||||
bool m_cancellable;
|
||||
bool m_cancelled;
|
||||
String m_status_text;
|
||||
u32 m_progress_range;
|
||||
u32 m_progress_value;
|
||||
|
||||
u32 m_base_progress_value;
|
||||
|
||||
State* m_saved_state;
|
||||
};
|
||||
|
||||
class ConsoleProgressCallback : public BaseProgressCallback
|
||||
{
|
||||
public:
|
||||
static const u32 COLUMNS = 78;
|
||||
|
||||
public:
|
||||
ConsoleProgressCallback();
|
||||
~ConsoleProgressCallback();
|
||||
|
||||
virtual void PushState() override;
|
||||
virtual void PopState() override;
|
||||
|
||||
virtual void SetCancellable(bool cancellable) override;
|
||||
virtual void SetStatusText(const char* text) override;
|
||||
virtual void SetProgressRange(u32 range) override;
|
||||
virtual void SetProgressValue(u32 value) override;
|
||||
|
||||
virtual void DisplayError(const char* message) override;
|
||||
virtual void DisplayWarning(const char* message) override;
|
||||
virtual void DisplayInformation(const char* message) override;
|
||||
virtual void DisplayDebugMessage(const char* message) override;
|
||||
|
||||
virtual void ModalError(const char* message) override;
|
||||
virtual bool ModalConfirmation(const char* message) override;
|
||||
virtual u32 ModalPrompt(const char* message, u32 num_options, ...) override;
|
||||
|
||||
private:
|
||||
void Clear();
|
||||
void Redraw(bool update_value_only);
|
||||
|
||||
float m_last_percent_complete;
|
||||
u32 m_last_bar_length;
|
||||
};
|
Loading…
Reference in New Issue