Put Windows timer functions into PBD namespace in preparation for moving them to libpbd
Add functions for get/set the Multimedia timer resolution, although we are really only interested in the minimum, this will facilitate testing Put timer utility functions inside nested namespaces as they are platform specific
This commit is contained in:
parent
4330db1aa7
commit
4ffe8ffc0f
@ -680,7 +680,7 @@ PortAudioBackend::samples_since_cycle_start ()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_cycle_timer.samples_since_cycle_start (utils::get_microseconds());
|
return m_cycle_timer.samples_since_cycle_start (PBD::get_microseconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1525,7 +1525,7 @@ PortAudioBackend::blocking_process_main(const float* interleaved_input_data,
|
|||||||
int64_t min_elapsed_us = 1000000;
|
int64_t min_elapsed_us = 1000000;
|
||||||
int64_t max_elapsed_us = 0;
|
int64_t max_elapsed_us = 0;
|
||||||
|
|
||||||
m_dsp_calc.set_start_timestamp_us (utils::get_microseconds());
|
m_dsp_calc.set_start_timestamp_us (PBD::get_microseconds());
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
/* Copy input audio data into input port buffers */
|
/* Copy input audio data into input port buffers */
|
||||||
@ -1551,7 +1551,7 @@ PortAudioBackend::blocking_process_main(const float* interleaved_input_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_last_cycle_start = m_cycle_timer.get_start();
|
m_last_cycle_start = m_cycle_timer.get_start();
|
||||||
m_cycle_timer.reset_start(utils::get_microseconds());
|
m_cycle_timer.reset_start(PBD::get_microseconds());
|
||||||
m_cycle_count++;
|
m_cycle_count++;
|
||||||
|
|
||||||
uint64_t cycle_diff_us = (m_cycle_timer.get_start() - m_last_cycle_start);
|
uint64_t cycle_diff_us = (m_cycle_timer.get_start() - m_last_cycle_start);
|
||||||
@ -1599,7 +1599,7 @@ PortAudioBackend::blocking_process_main(const float* interleaved_input_data,
|
|||||||
_processed_samples += _samples_per_period;
|
_processed_samples += _samples_per_period;
|
||||||
|
|
||||||
/* calculate DSP load */
|
/* calculate DSP load */
|
||||||
m_dsp_calc.set_stop_timestamp_us (utils::get_microseconds());
|
m_dsp_calc.set_stop_timestamp_us (PBD::get_microseconds());
|
||||||
_dsp_load = m_dsp_calc.get_dsp_load();
|
_dsp_load = m_dsp_calc.get_dsp_load();
|
||||||
|
|
||||||
DEBUG_TIMING(string_compose("DSP Load: %1\n", _dsp_load));
|
DEBUG_TIMING(string_compose("DSP Load: %1\n", _dsp_load));
|
||||||
|
@ -27,6 +27,90 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
UINT&
|
||||||
|
old_timer_resolution ()
|
||||||
|
{
|
||||||
|
static UINT timer_res_ms = 0;
|
||||||
|
return timer_res_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anon namespace
|
||||||
|
|
||||||
|
namespace PBD {
|
||||||
|
|
||||||
|
namespace MMTIMERS {
|
||||||
|
|
||||||
|
bool
|
||||||
|
set_min_resolution ()
|
||||||
|
{
|
||||||
|
TIMECAPS caps;
|
||||||
|
|
||||||
|
if (timeGetDevCaps (&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
|
||||||
|
DEBUG_TIMING ("Could not get timer device capabilities.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return set_resolution(caps.wPeriodMin);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
set_resolution (uint32_t timer_resolution_ms)
|
||||||
|
{
|
||||||
|
TIMECAPS caps;
|
||||||
|
|
||||||
|
if (timeGetDevCaps (&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
|
||||||
|
DEBUG_TIMING ("Could not get timer device capabilities.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT old_timer_res = caps.wPeriodMin;
|
||||||
|
|
||||||
|
if (timeBeginPeriod(timer_resolution_ms) != TIMERR_NOERROR) {
|
||||||
|
DEBUG_TIMING(
|
||||||
|
string_compose("Could not set minimum timer resolution to %1(ms)\n",
|
||||||
|
timer_resolution_ms));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
old_timer_resolution () = old_timer_res;
|
||||||
|
|
||||||
|
DEBUG_TIMING (string_compose ("Multimedia timer resolution set to %1(ms)\n",
|
||||||
|
caps.wPeriodMin));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_resolution (uint32_t& timer_resolution_ms)
|
||||||
|
{
|
||||||
|
TIMECAPS caps;
|
||||||
|
|
||||||
|
if (timeGetDevCaps(&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
|
||||||
|
DEBUG_TIMING ("Could not get timer device capabilities.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
timer_resolution_ms = caps.wPeriodMin;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
reset_resolution ()
|
||||||
|
{
|
||||||
|
if (old_timer_resolution ()) {
|
||||||
|
if (timeEndPeriod (old_timer_resolution ()) != TIMERR_NOERROR) {
|
||||||
|
DEBUG_TIMING ("Could not reset timer resolution.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_TIMING (string_compose ("Multimedia timer resolution set to %1(ms)\n",
|
||||||
|
old_timer_resolution ()));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace MMTIMERS
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
bool&
|
bool&
|
||||||
qpc_frequency_success ()
|
qpc_frequency_success ()
|
||||||
{
|
{
|
||||||
@ -48,76 +132,52 @@ qpc_frequency ()
|
|||||||
return freq;
|
return freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT&
|
LARGE_INTEGER
|
||||||
old_timer_resolution ()
|
qpc_frequency_cached ()
|
||||||
{
|
{
|
||||||
static UINT timer_res_ms = 0;
|
static LARGE_INTEGER frequency = qpc_frequency ();
|
||||||
return timer_res_ms;
|
return frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anon namespace
|
} // anon namespace
|
||||||
|
|
||||||
namespace utils {
|
namespace QPC {
|
||||||
|
|
||||||
bool
|
bool
|
||||||
set_min_timer_resolution ()
|
get_timer_valid ()
|
||||||
{
|
{
|
||||||
TIMECAPS caps;
|
// setup caching the timer frequency
|
||||||
|
qpc_frequency_cached ();
|
||||||
if (timeGetDevCaps (&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
|
return qpc_frequency_success ();
|
||||||
DEBUG_TIMING ("Could not get timer device capabilities.\n");
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
old_timer_resolution () = caps.wPeriodMin;
|
|
||||||
if (timeBeginPeriod (caps.wPeriodMin) != TIMERR_NOERROR) {
|
|
||||||
DEBUG_TIMING (string_compose (
|
|
||||||
"Could not set minimum timer resolution to %1(ms)\n", caps.wPeriodMin));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_TIMING (string_compose ("Multimedia timer resolution set to %1(ms)\n",
|
|
||||||
caps.wPeriodMin));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
reset_timer_resolution ()
|
|
||||||
{
|
|
||||||
if (old_timer_resolution ()) {
|
|
||||||
if (timeEndPeriod (old_timer_resolution ()) != TIMERR_NOERROR) {
|
|
||||||
DEBUG_TIMING ("Could not reset timer resolution.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_TIMING (string_compose ("Multimedia timer resolution set to %1(ms)\n",
|
|
||||||
old_timer_resolution ()));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
get_microseconds ()
|
get_microseconds ()
|
||||||
{
|
{
|
||||||
static LARGE_INTEGER frequency = qpc_frequency ();
|
|
||||||
LARGE_INTEGER current_val;
|
LARGE_INTEGER current_val;
|
||||||
|
|
||||||
if (qpc_frequency_success()) {
|
if (qpc_frequency_success()) {
|
||||||
|
|
||||||
// MS docs say this will always succeed for systems >= XP but it may
|
// MS docs say this will always succeed for systems >= XP but it may
|
||||||
// not return a monotonic value with non-invariant TSC's etc
|
// not return a monotonic value with non-invariant TSC's etc
|
||||||
if (QueryPerformanceCounter(¤t_val) != 0) {
|
if (QueryPerformanceCounter(¤t_val) != 0) {
|
||||||
return (int64_t)(((double)current_val.QuadPart) /
|
return (int64_t)(((double)current_val.QuadPart) /
|
||||||
((double)frequency.QuadPart) * 1000000.0);
|
((double)qpc_frequency_cached().QuadPart) * 1000000.0);
|
||||||
} else {
|
|
||||||
DEBUG_TIMING ("Could not get QPC timer\n");
|
|
||||||
}
|
}
|
||||||
return -1;
|
}
|
||||||
|
DEBUG_TIMING ("Could not get QPC timer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QPC
|
||||||
|
|
||||||
|
int64_t
|
||||||
|
get_microseconds ()
|
||||||
|
{
|
||||||
|
if (qpc_frequency_success()) {
|
||||||
|
return QPC::get_microseconds ();
|
||||||
}
|
}
|
||||||
// For XP systems that don't support a high-res performance counter
|
// For XP systems that don't support a high-res performance counter
|
||||||
return g_get_monotonic_time ();
|
return g_get_monotonic_time ();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace PBD
|
||||||
|
@ -21,22 +21,66 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace utils {
|
namespace PBD {
|
||||||
|
|
||||||
bool set_min_timer_resolution ();
|
namespace MMTIMERS {
|
||||||
|
|
||||||
bool reset_timer_resolution ();
|
/**
|
||||||
|
* Set the minimum Multimedia Timer resolution as supported by the system
|
||||||
|
* @return true if min timer resolution was successfully set
|
||||||
|
*
|
||||||
|
* Call reset_resolution to restore old timer resolution
|
||||||
|
*/
|
||||||
|
bool set_min_resolution ();
|
||||||
|
|
||||||
/** The highest resolution timer source provided by the system. On Vista and
|
/**
|
||||||
|
* Get current Multimedia Timer resolution
|
||||||
|
* @return true if getting the timer value was successful
|
||||||
|
*/
|
||||||
|
bool get_resolution(uint32_t& timer_resolution_us);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set current Multimedia Timer resolution
|
||||||
|
* @return true if setting the timer value was successful
|
||||||
|
*/
|
||||||
|
bool set_resolution(uint32_t timer_resolution_us);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the Multimedia Timer back to what it was originally before
|
||||||
|
* setting the timer resolution.
|
||||||
|
*/
|
||||||
|
bool reset_resolution ();
|
||||||
|
|
||||||
|
} // namespace MMTIMERS
|
||||||
|
|
||||||
|
namespace QPC {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if QueryPerformanceCounter is usable as a timer source
|
||||||
|
*/
|
||||||
|
bool get_timer_valid ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the value of the performance counter converted to microseconds
|
||||||
|
*
|
||||||
|
* If get_counter_valid returns true then get_microseconds will always
|
||||||
|
* return a positive value. If QPC is not supported(OS < XP) then -1 is
|
||||||
|
* returned but the MS docs say that this won't occur for systems >= XP.
|
||||||
|
*/
|
||||||
|
int64_t get_microseconds ();
|
||||||
|
|
||||||
|
} // namespace QPC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The highest resolution timer source provided by the system. On Vista and
|
||||||
* above this is the value returned by QueryPerformanceCounter(QPC). On XP,
|
* above this is the value returned by QueryPerformanceCounter(QPC). On XP,
|
||||||
* this will QPC if supported or otherwise g_get_monotonic_time will be used.
|
* this will QPC if supported or otherwise g_get_monotonic_time will be used.
|
||||||
*
|
*
|
||||||
* @return A timer value in microseconds or -1 in the event that the reading
|
* @return A timer value in microseconds or -1 in the event that the reading
|
||||||
* the timer source fails, but the MS docs say that this won't occur for
|
* the timer source fails.
|
||||||
* systems >= XP
|
|
||||||
*/
|
*/
|
||||||
int64_t get_microseconds ();
|
int64_t get_microseconds ();
|
||||||
|
|
||||||
}
|
} // namespace PBD
|
||||||
|
|
||||||
#endif // WIN_UTILS_H
|
#endif // WIN_UTILS_H
|
||||||
|
@ -346,7 +346,7 @@ WinMMEMidiInputDevice::enqueue_midi_msg (const uint8_t* midi_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// don't use winmme timestamps for now
|
// don't use winmme timestamps for now
|
||||||
uint64_t ts = utils::get_microseconds ();
|
uint64_t ts = PBD::get_microseconds ();
|
||||||
|
|
||||||
DEBUG_TIMING (string_compose (
|
DEBUG_TIMING (string_compose (
|
||||||
"Enqueing MIDI data device: %1 with timestamp: %2 and size %3\n",
|
"Enqueing MIDI data device: %1 with timestamp: %2 and size %3\n",
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace utils;
|
|
||||||
|
|
||||||
WinMMEMidiIO::WinMMEMidiIO()
|
WinMMEMidiIO::WinMMEMidiIO()
|
||||||
: m_active (false)
|
: m_active (false)
|
||||||
@ -136,7 +135,7 @@ WinMMEMidiIO::start ()
|
|||||||
m_run = true;
|
m_run = true;
|
||||||
DEBUG_MIDI ("Starting MIDI driver\n");
|
DEBUG_MIDI ("Starting MIDI driver\n");
|
||||||
|
|
||||||
set_min_timer_resolution();
|
PBD::MMTIMERS::set_min_resolution();
|
||||||
discover();
|
discover();
|
||||||
start_devices ();
|
start_devices ();
|
||||||
}
|
}
|
||||||
@ -156,7 +155,7 @@ WinMMEMidiIO::stop ()
|
|||||||
cleanup ();
|
cleanup ();
|
||||||
pthread_mutex_unlock (&m_device_lock);
|
pthread_mutex_unlock (&m_device_lock);
|
||||||
|
|
||||||
reset_timer_resolution();
|
PBD::MMTIMERS::reset_resolution();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -390,7 +390,7 @@ WinMMEMidiOutputDevice::midi_output_thread ()
|
|||||||
DEBUG_MIDI ("WinMMEMidiOut: MIDI buffer underrun, shouldn't occur\n");
|
DEBUG_MIDI ("WinMMEMidiOut: MIDI buffer underrun, shouldn't occur\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
uint64_t current_time = utils::get_microseconds ();
|
uint64_t current_time = PBD::get_microseconds ();
|
||||||
|
|
||||||
DEBUG_TIMING (string_compose (
|
DEBUG_TIMING (string_compose (
|
||||||
"WinMMEMidiOut: h.time = %1, current_time = %2\n", h.time, current_time));
|
"WinMMEMidiOut: h.time = %1, current_time = %2\n", h.time, current_time));
|
||||||
@ -408,7 +408,7 @@ WinMMEMidiOutputDevice::midi_output_thread ()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t wakeup_time = utils::get_microseconds ();
|
uint64_t wakeup_time = PBD::get_microseconds ();
|
||||||
DEBUG_TIMING (string_compose ("WinMMEMidiOut: woke up at %1(ms)\n",
|
DEBUG_TIMING (string_compose ("WinMMEMidiOut: woke up at %1(ms)\n",
|
||||||
((double)wakeup_time) / 1000.0));
|
((double)wakeup_time) / 1000.0));
|
||||||
if (wakeup_time > h.time) {
|
if (wakeup_time > h.time) {
|
||||||
|
Loading…
Reference in New Issue
Block a user