git-svn-id: svn+ssh://jackaudio.org/trunk/jack@350 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
@@ -13,7 +13,7 @@ dnl micro version = incremented when implementation-only | |||||
dnl changes are made | dnl changes are made | ||||
dnl --- | dnl --- | ||||
JACK_MAJOR_VERSION=0 | JACK_MAJOR_VERSION=0 | ||||
JACK_MINOR_VERSION=62 | |||||
JACK_MINOR_VERSION=63 | |||||
JACK_MICRO_VERSION=0 | JACK_MICRO_VERSION=0 | ||||
dnl --- | dnl --- | ||||
@@ -41,7 +41,7 @@ dnl slacker than this, and closer to those for the JACK version | |||||
dnl number. | dnl number. | ||||
dnl --- | dnl --- | ||||
JACK_API_CURRENT=0 | JACK_API_CURRENT=0 | ||||
JACK_API_REVISION=10 | |||||
JACK_API_REVISION=11 | |||||
JACK_API_AGE=0 | JACK_API_AGE=0 | ||||
AC_SUBST(JACK_MAJOR_VERSION) | AC_SUBST(JACK_MAJOR_VERSION) | ||||
@@ -35,7 +35,7 @@ | |||||
#include <jack/hdsp.h> | #include <jack/hdsp.h> | ||||
#include <jack/ice1712.h> | #include <jack/ice1712.h> | ||||
#include <jack/generic.h> | #include <jack/generic.h> | ||||
#include <jack/cycles.h> | |||||
#include <jack/time.h> | |||||
extern void store_work_time (int); | extern void store_work_time (int); | ||||
extern void store_wait_time (int); | extern void store_wait_time (int); | ||||
@@ -134,7 +134,7 @@ alsa_driver_generic_hardware (alsa_driver_t *driver) | |||||
} | } | ||||
static int | static int | ||||
alsa_driver_hw_specific (alsa_driver_t *driver, int hw_monitoring) | |||||
alsa_driver_hw_specific (alsa_driver_t *driver, int hw_monitoring, int hw_metering) | |||||
{ | { | ||||
int err; | int err; | ||||
@@ -172,6 +172,14 @@ alsa_driver_hw_specific (alsa_driver_t *driver, int hw_monitoring) | |||||
driver->has_clock_sync_reporting = FALSE; | driver->has_clock_sync_reporting = FALSE; | ||||
} | } | ||||
if (driver->hw->capabilities & Cap_HardwareMetering) { | |||||
driver->has_hw_metering = TRUE; | |||||
driver->hw_metering = hw_metering; | |||||
} else { | |||||
driver->has_hw_metering = FALSE; | |||||
driver->hw_metering = FALSE; | |||||
} | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -860,7 +868,7 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float *delay | |||||
nfds++; | nfds++; | ||||
} | } | ||||
poll_enter = get_cycles (); | |||||
poll_enter = jack_get_microseconds (); | |||||
if (poll (driver->pfd, nfds, (int) floor ((1.5f * driver->period_usecs) / 1000.0f)) < 0) { | if (poll (driver->pfd, nfds, (int) floor ((1.5f * driver->period_usecs) / 1000.0f)) < 0) { | ||||
if (errno == EINTR) { | if (errno == EINTR) { | ||||
@@ -880,7 +888,7 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float *delay | |||||
} | } | ||||
poll_ret = get_cycles (); | |||||
poll_ret = jack_get_microseconds (); | |||||
if (extra_fd < 0) { | if (extra_fd < 0) { | ||||
if (driver->poll_next && poll_ret > driver->poll_next) { | if (driver->poll_next && poll_ret > driver->poll_next) { | ||||
@@ -888,7 +896,7 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float *delay | |||||
} | } | ||||
driver->poll_last = poll_ret; | driver->poll_last = poll_ret; | ||||
driver->poll_next = poll_ret + (unsigned long long) floor ((driver->period_usecs * driver->cpu_mhz)); | driver->poll_next = poll_ret + (unsigned long long) floor ((driver->period_usecs * driver->cpu_mhz)); | ||||
driver->engine->control->current_time.cycles = poll_ret; | |||||
driver->engine->control->current_time.usecs = poll_ret; | |||||
} | } | ||||
#ifdef DEBUG_WAKEUP | #ifdef DEBUG_WAKEUP | ||||
@@ -1228,6 +1236,11 @@ alsa_driver_attach (alsa_driver_t *driver, jack_engine_t *engine) | |||||
break; | break; | ||||
} | } | ||||
if (driver->hw_metering) { | |||||
jack_port_set_peak_function(port, driver->hw->get_hardware_peak); | |||||
jack_port_set_power_function(port, driver->hw->get_hardware_power); | |||||
} | |||||
/* XXX fix this so that it can handle: systemic (external) latency | /* XXX fix this so that it can handle: systemic (external) latency | ||||
*/ | */ | ||||
@@ -1246,6 +1259,11 @@ alsa_driver_attach (alsa_driver_t *driver, jack_engine_t *engine) | |||||
break; | break; | ||||
} | } | ||||
if (driver->hw_metering) { | |||||
jack_port_set_peak_function(port, driver->hw->get_hardware_peak); | |||||
jack_port_set_power_function(port, driver->hw->get_hardware_power); | |||||
} | |||||
/* XXX fix this so that it can handle: systemic (external) latency | /* XXX fix this so that it can handle: systemic (external) latency | ||||
*/ | */ | ||||
@@ -1397,6 +1415,7 @@ alsa_driver_new (char *name, char *alsa_device, | |||||
jack_nframes_t user_nperiods, | jack_nframes_t user_nperiods, | ||||
jack_nframes_t rate, | jack_nframes_t rate, | ||||
int hw_monitoring, | int hw_monitoring, | ||||
int hw_metering, | |||||
int capturing, | int capturing, | ||||
int playing, | int playing, | ||||
DitherAlgorithm dither, | DitherAlgorithm dither, | ||||
@@ -1406,9 +1425,9 @@ alsa_driver_new (char *name, char *alsa_device, | |||||
alsa_driver_t *driver; | alsa_driver_t *driver; | ||||
printf ("creating alsa driver ... %s|%lu|%lu|%lu|%s|%s\n", | |||||
printf ("creating alsa driver ... %s|%lu|%lu|%lu|%s|%s|%s\n", | |||||
alsa_device, frames_per_cycle, user_nperiods, rate, | alsa_device, frames_per_cycle, user_nperiods, rate, | ||||
hw_monitoring ? "hwmon":"swmon", soft_mode ? "soft-mode":"rt"); | |||||
hw_monitoring ? "hwmon":"swmon", hw_metering ? "hwmeter":"swmeter", soft_mode ? "soft-mode":"rt"); | |||||
driver = (alsa_driver_t *) calloc (1, sizeof (alsa_driver_t)); | driver = (alsa_driver_t *) calloc (1, sizeof (alsa_driver_t)); | ||||
@@ -1560,7 +1579,7 @@ alsa_driver_new (char *name, char *alsa_device, | |||||
} | } | ||||
} | } | ||||
alsa_driver_hw_specific (driver, hw_monitoring); | |||||
alsa_driver_hw_specific (driver, hw_monitoring, hw_metering); | |||||
driver->client = client; | driver->client = client; | ||||
@@ -1630,6 +1649,7 @@ alsa_usage () | |||||
" -p,--period <n> \tframes per period (default: 1024)\n" | " -p,--period <n> \tframes per period (default: 1024)\n" | ||||
" -n,--nperiods <n> \tnumber of periods in hardware buffer (default: 2)\n" | " -n,--nperiods <n> \tnumber of periods in hardware buffer (default: 2)\n" | ||||
" -H,--hwmon \tuse hardware monitoring, if available (default: no)\n" | " -H,--hwmon \tuse hardware monitoring, if available (default: no)\n" | ||||
" -M,--hwmeter \tuse hardware metering, if available (default: no)\n" | |||||
" -D,--duplex \tduplex I/O (default: yes)\n" | " -D,--duplex \tduplex I/O (default: yes)\n" | ||||
" -C,--capture \tcapture input (default: duplex)\n" | " -C,--capture \tcapture input (default: duplex)\n" | ||||
" -P,--playback\tplayback output (default: duplex)\n" | " -P,--playback\tplayback output (default: duplex)\n" | ||||
@@ -1649,6 +1669,34 @@ alsa_error (char *type, char *value) | |||||
alsa_usage(); | alsa_usage(); | ||||
} | } | ||||
static int | |||||
dither_opt (char c, DitherAlgorithm* dither) | |||||
{ | |||||
switch (*optarg) { | |||||
case '-': | |||||
*dither = None; | |||||
break; | |||||
case 'r': | |||||
*dither = Rectangular; | |||||
break; | |||||
case 's': | |||||
*dither = Shaped; | |||||
break; | |||||
case 't': | |||||
*dither = Triangular; | |||||
break; | |||||
default: | |||||
alsa_error ("illegal dithering mode", ""); | |||||
return -1; | |||||
} | |||||
return 0; | |||||
} | |||||
/* DRIVER "PLUGIN" INTERFACE */ | /* DRIVER "PLUGIN" INTERFACE */ | ||||
const char driver_client_name[] = "alsa_pcm"; | const char driver_client_name[] = "alsa_pcm"; | ||||
@@ -1661,11 +1709,13 @@ driver_initialize (jack_client_t *client, int argc, char **argv) | |||||
unsigned long user_nperiods = 2; | unsigned long user_nperiods = 2; | ||||
char *pcm_name = "default"; | char *pcm_name = "default"; | ||||
int hw_monitoring = FALSE; | int hw_monitoring = FALSE; | ||||
int hw_metering = FALSE; | |||||
int capture = FALSE; | int capture = FALSE; | ||||
int playback = FALSE; | int playback = FALSE; | ||||
int soft_mode = FALSE; | int soft_mode = FALSE; | ||||
DitherAlgorithm dither = None; | DitherAlgorithm dither = None; | ||||
int opt; | int opt; | ||||
char *envvar; | |||||
char optstring[2]; /* string made from opt char */ | char optstring[2]; /* string made from opt char */ | ||||
struct option long_options[] = | struct option long_options[] = | ||||
{ | { | ||||
@@ -1673,6 +1723,7 @@ driver_initialize (jack_client_t *client, int argc, char **argv) | |||||
{ "duplex", 0, NULL, 'D' }, | { "duplex", 0, NULL, 'D' }, | ||||
{ "device", 1, NULL, 'd' }, | { "device", 1, NULL, 'd' }, | ||||
{ "hwmon", 0, NULL, 'H' }, | { "hwmon", 0, NULL, 'H' }, | ||||
{ "hwmeter", 0, NULL, 'M' }, | |||||
{ "help", 0, NULL, 'h' }, | { "help", 0, NULL, 'h' }, | ||||
{ "playback", 0, NULL, 'P' }, | { "playback", 0, NULL, 'P' }, | ||||
{ "period", 1, NULL, 'p' }, | { "period", 1, NULL, 'p' }, | ||||
@@ -1683,13 +1734,57 @@ driver_initialize (jack_client_t *client, int argc, char **argv) | |||||
{ 0, 0, 0, 0 } | { 0, 0, 0, 0 } | ||||
}; | }; | ||||
/* before we do anything else, see if there are environment variables | |||||
for each parameter. | |||||
*/ | |||||
if ((envvar = getenv ("JACK_ALSA_DEVICE")) != NULL) { | |||||
pcm_name = envvar; | |||||
} | |||||
if ((envvar = getenv ("JACK_ALSA_HWMON")) != NULL) { | |||||
hw_monitoring = TRUE; | |||||
} | |||||
if ((envvar = getenv ("JACK_ALSA_SOFTMODE")) != NULL) { | |||||
soft_mode = TRUE; | |||||
} | |||||
if ((envvar = getenv ("JACK_ALSA_PERIOD_FRAMES")) != NULL) { | |||||
frames_per_interrupt = atoi (envvar); | |||||
} | |||||
if ((envvar = getenv ("JACK_ALSA_PERIODS")) != NULL) { | |||||
user_nperiods = atoi (envvar); | |||||
} | |||||
if ((envvar = getenv ("JACK_ALSA_SRATE")) != NULL) { | |||||
srate = atoi (envvar); | |||||
} | |||||
if ((envvar = getenv ("JACK_ALSA_DITHER")) != NULL) { | |||||
if (dither_opt (*envvar, &dither)) { | |||||
return NULL; | |||||
} | |||||
} | |||||
if ((envvar = getenv ("JACK_ALSA_CAPTURE")) != NULL) { | |||||
capture = atoi (envvar); | |||||
} | |||||
if ((envvar = getenv ("JACK_ALSA_PLAYBACK")) != NULL) { | |||||
playback = atoi (envvar); | |||||
} | |||||
/* | /* | ||||
* Setting optind back to zero is a hack to reinitialize a new | * Setting optind back to zero is a hack to reinitialize a new | ||||
* getopts() loop. See declaration in <getopt.h>. | * getopts() loop. See declaration in <getopt.h>. | ||||
*/ | */ | ||||
optind = 0; | optind = 0; | ||||
opterr = 0; | opterr = 0; | ||||
while ((opt = getopt_long(argc, argv, "-CDd:HPp:r:n:sz::", | |||||
while ((opt = getopt_long(argc, argv, "-CDd:HMPp:r:n:sz::", | |||||
long_options, NULL)) | long_options, NULL)) | ||||
!= EOF) { | != EOF) { | ||||
switch (opt) { | switch (opt) { | ||||
@@ -1715,6 +1810,10 @@ driver_initialize (jack_client_t *client, int argc, char **argv) | |||||
alsa_usage(); | alsa_usage(); | ||||
return NULL; | return NULL; | ||||
case 'M': | |||||
hw_metering = TRUE; | |||||
break; | |||||
case 'P': | case 'P': | ||||
playback = TRUE; | playback = TRUE; | ||||
break; | break; | ||||
@@ -1739,26 +1838,7 @@ driver_initialize (jack_client_t *client, int argc, char **argv) | |||||
if (optarg == NULL) { | if (optarg == NULL) { | ||||
dither = None; | dither = None; | ||||
} else { | } else { | ||||
switch (*optarg) { | |||||
case '-': | |||||
dither = None; | |||||
break; | |||||
case 'r': | |||||
dither = Rectangular; | |||||
break; | |||||
case 's': | |||||
dither = Shaped; | |||||
break; | |||||
case 't': | |||||
dither = Triangular; | |||||
break; | |||||
default: | |||||
alsa_error("dithering mode", optarg); | |||||
if (dither_opt (*optarg, &dither)) { | |||||
return NULL; | return NULL; | ||||
} | } | ||||
} | } | ||||
@@ -1784,7 +1864,7 @@ driver_initialize (jack_client_t *client, int argc, char **argv) | |||||
} | } | ||||
return alsa_driver_new ("alsa_pcm", pcm_name, client, frames_per_interrupt, | return alsa_driver_new ("alsa_pcm", pcm_name, client, frames_per_interrupt, | ||||
user_nperiods, srate, hw_monitoring, capture, | |||||
user_nperiods, srate, hw_monitoring, hw_metering, capture, | |||||
playback, dither, soft_mode); | playback, dither, soft_mode); | ||||
} | } | ||||
@@ -174,6 +174,16 @@ static int hdsp_change_sample_clock (jack_hardware_t *hw, SampleClockMode mode) | |||||
return -1; | return -1; | ||||
} | } | ||||
static double hdsp_get_hardware_peak (jack_port_t *port, jack_nframes_t frame) | |||||
{ | |||||
return 0; | |||||
} | |||||
static double hdsp_get_hardware_power (jack_port_t *port, jack_nframes_t frame) | |||||
{ | |||||
return 0; | |||||
} | |||||
void | void | ||||
jack_alsa_hdsp_release (jack_hardware_t *hw) | jack_alsa_hdsp_release (jack_hardware_t *hw) | ||||
@@ -198,14 +208,16 @@ jack_alsa_hdsp_hw_new (alsa_driver_t *driver) | |||||
/* Not using clock lock-sync-whatever in home hardware setup */ | /* Not using clock lock-sync-whatever in home hardware setup */ | ||||
/* yet. Will write this code when can test it. */ | /* yet. Will write this code when can test it. */ | ||||
/* hw->capabilities = Cap_HardwareMonitoring|Cap_AutoSync|Cap_WordClock|Cap_ClockMaster|Cap_ClockLockReporting; */ | /* hw->capabilities = Cap_HardwareMonitoring|Cap_AutoSync|Cap_WordClock|Cap_ClockMaster|Cap_ClockLockReporting; */ | ||||
hw->capabilities = Cap_HardwareMonitoring; | |||||
hw->capabilities = Cap_HardwareMonitoring | Cap_HardwareMetering; | |||||
hw->input_monitor_mask = 0; | hw->input_monitor_mask = 0; | ||||
hw->private = 0; | hw->private = 0; | ||||
hw->set_input_monitor_mask = hdsp_set_input_monitor_mask; | hw->set_input_monitor_mask = hdsp_set_input_monitor_mask; | ||||
hw->change_sample_clock = hdsp_change_sample_clock; | hw->change_sample_clock = hdsp_change_sample_clock; | ||||
hw->release = jack_alsa_hdsp_release; | hw->release = jack_alsa_hdsp_release; | ||||
hw->get_hardware_peak = hdsp_get_hardware_peak; | |||||
hw->get_hardware_power = hdsp_get_hardware_power; | |||||
h = (hdsp_t *) malloc (sizeof (hdsp_t)); | h = (hdsp_t *) malloc (sizeof (hdsp_t)); | ||||
h->driver = driver; | h->driver = driver; | ||||
hw->private = h; | hw->private = h; | ||||
@@ -98,6 +98,7 @@ typedef struct { | |||||
char soft_mode : 1; | char soft_mode : 1; | ||||
char hw_monitoring : 1; | char hw_monitoring : 1; | ||||
char hw_metering : 1; | |||||
char all_monitor_in : 1; | char all_monitor_in : 1; | ||||
char capture_and_playback_not_synced : 1; | char capture_and_playback_not_synced : 1; | ||||
char interleaved : 1; | char interleaved : 1; | ||||
@@ -115,7 +116,7 @@ typedef struct { | |||||
unsigned long next_clock_sync_listener_id; | unsigned long next_clock_sync_listener_id; | ||||
char has_clock_sync_reporting : 1; | char has_clock_sync_reporting : 1; | ||||
char has_hw_monitoring : 1; | char has_hw_monitoring : 1; | ||||
char has_hw_metering : 1; | |||||
} alsa_driver_t; | } alsa_driver_t; | ||||
static __inline__ void alsa_driver_mark_channel_done (alsa_driver_t *driver, channel_t chn) { | static __inline__ void alsa_driver_mark_channel_done (alsa_driver_t *driver, channel_t chn) { | ||||
@@ -87,7 +87,6 @@ struct _jack_engine { | |||||
char asio_mode; | char asio_mode; | ||||
int reordered; | int reordered; | ||||
int watchdog_check; | int watchdog_check; | ||||
float cpu_mhz; | |||||
struct _jack_client_internal *current_client; | struct _jack_client_internal *current_client; | ||||
@@ -34,7 +34,8 @@ typedef enum { | |||||
Cap_AutoSync = 0x2, | Cap_AutoSync = 0x2, | ||||
Cap_WordClock = 0x4, | Cap_WordClock = 0x4, | ||||
Cap_ClockMaster = 0x8, | Cap_ClockMaster = 0x8, | ||||
Cap_ClockLockReporting = 0x10 | |||||
Cap_ClockLockReporting = 0x10, | |||||
Cap_HardwareMetering = 0x20 | |||||
} Capabilities; | } Capabilities; | ||||
struct _jack_hardware; | struct _jack_hardware; | ||||
@@ -42,6 +43,9 @@ struct _jack_hardware; | |||||
typedef void (*JackHardwareReleaseFunction)(struct _jack_hardware *); | typedef void (*JackHardwareReleaseFunction)(struct _jack_hardware *); | ||||
typedef int (*JackHardwareSetInputMonitorMaskFunction)(struct _jack_hardware *, unsigned long); | typedef int (*JackHardwareSetInputMonitorMaskFunction)(struct _jack_hardware *, unsigned long); | ||||
typedef int (*JackHardwareChangeSampleClockFunction)(struct _jack_hardware *, SampleClockMode); | typedef int (*JackHardwareChangeSampleClockFunction)(struct _jack_hardware *, SampleClockMode); | ||||
typedef double (*JackHardwareGetHardwarePeak)(jack_port_t *port, jack_nframes_t frames); | |||||
typedef double (*JackHardwareGetHardwarePower)(jack_port_t *port, jack_nframes_t frames); | |||||
typedef struct _jack_hardware { | typedef struct _jack_hardware { | ||||
@@ -51,7 +55,8 @@ typedef struct _jack_hardware { | |||||
JackHardwareChangeSampleClockFunction change_sample_clock; | JackHardwareChangeSampleClockFunction change_sample_clock; | ||||
JackHardwareSetInputMonitorMaskFunction set_input_monitor_mask; | JackHardwareSetInputMonitorMaskFunction set_input_monitor_mask; | ||||
JackHardwareReleaseFunction release; | JackHardwareReleaseFunction release; | ||||
JackHardwareGetHardwarePeak get_hardware_peak; | |||||
JackHardwareGetHardwarePower get_hardware_power; | |||||
void *private; | void *private; | ||||
} jack_hardware_t; | } jack_hardware_t; | ||||
@@ -33,11 +33,11 @@ | |||||
#include <jack/types.h> | #include <jack/types.h> | ||||
#include <jack/port.h> | #include <jack/port.h> | ||||
#include <jack/transport.h> | #include <jack/transport.h> | ||||
#include <jack/cycles.h> | |||||
#include <jack/time.h> | |||||
#ifdef DEBUG_ENABLED | #ifdef DEBUG_ENABLED | ||||
#define DEBUG(format,args...) \ | #define DEBUG(format,args...) \ | ||||
printf ("jack:%5d:%Lu %s:%s:%d: " format "\n", getpid(), get_cycles(), __FILE__, __FUNCTION__, __LINE__ , ## args) | |||||
printf ("jack:%5d:%Lu %s:%s:%d: " format "\n", getpid(), jack_get_microseconds(), __FILE__, __FUNCTION__, __LINE__ , ## args) | |||||
#else | #else | ||||
#define DEBUG(format,args...) | #define DEBUG(format,args...) | ||||
#endif | #endif | ||||
@@ -69,7 +69,7 @@ typedef struct _time_info | |||||
{ | { | ||||
jack_nframes_t frame; | jack_nframes_t frame; | ||||
jack_nframes_t frame_rate; | jack_nframes_t frame_rate; | ||||
cycles_t cycles; | |||||
jack_time_t usecs; | |||||
jack_transport_state_t transport_state; | jack_transport_state_t transport_state; | ||||
jack_nframes_t loop_start; | jack_nframes_t loop_start; | ||||
jack_nframes_t loop_end; | jack_nframes_t loop_end; | ||||
@@ -94,7 +94,7 @@ typedef struct _time_info | |||||
typedef struct { | typedef struct { | ||||
volatile unsigned long long guard1; | volatile unsigned long long guard1; | ||||
volatile jack_nframes_t frames; | volatile jack_nframes_t frames; | ||||
volatile cycles_t stamp; | |||||
volatile jack_time_t stamp; | |||||
volatile unsigned long long guard2; | volatile unsigned long long guard2; | ||||
} jack_frame_timer_t; | } jack_frame_timer_t; | ||||
@@ -302,8 +302,6 @@ void handle_internal_client_request (jack_control_t*, jack_request_t*); | |||||
extern char *jack_server_dir; | extern char *jack_server_dir; | ||||
extern int jack_get_mhz (void); | |||||
extern void jack_error (const char *fmt, ...); | extern void jack_error (const char *fmt, ...); | ||||
#endif /* __jack_internal_h__ */ | #endif /* __jack_internal_h__ */ | ||||
@@ -550,8 +550,8 @@ jack_nframes_t jack_frame_time (const jack_client_t *); | |||||
/** | /** | ||||
* This returns the current CPU load estimated by JACK | * This returns the current CPU load estimated by JACK | ||||
* as a percentage. The load is computed by measuring | * as a percentage. The load is computed by measuring | ||||
* the number of cycles it took to execute all clients | |||||
* as a fraction of the total number of cycles | |||||
* the amount of time it took to execute all clients | |||||
* as a fraction of the total amount of time | |||||
* represented by the data that was processed. | * represented by the data that was processed. | ||||
*/ | */ | ||||
float jack_cpu_load (jack_client_t *client); | float jack_cpu_load (jack_client_t *client); | ||||
@@ -33,6 +33,13 @@ typedef unsigned long jack_nframes_t; | |||||
*/ | */ | ||||
#define JACK_MAX_FRAMES ULONG_MAX; | #define JACK_MAX_FRAMES ULONG_MAX; | ||||
/** | |||||
* Type used to represent the value of free running | |||||
* monotonic clock with units of microseconds. | |||||
*/ | |||||
typedef unsigned long long jack_time_t; | |||||
/** | /** | ||||
* jack_port_t is an opaque type. You may only access it using the API provided. | * jack_port_t is an opaque type. You may only access it using the API provided. | ||||
*/ | */ | ||||
@@ -43,7 +43,7 @@ | |||||
#include <jack/internal.h> | #include <jack/internal.h> | ||||
#include <jack/engine.h> | #include <jack/engine.h> | ||||
#include <jack/driver.h> | #include <jack/driver.h> | ||||
#include <jack/cycles.h> | |||||
#include <jack/time.h> | |||||
#include <jack/version.h> | #include <jack/version.h> | ||||
#ifdef USE_CAPABILITIES | #ifdef USE_CAPABILITIES | ||||
@@ -458,13 +458,11 @@ jack_process (jack_engine_t *engine, jack_nframes_t nframes) | |||||
jack_client_internal_t *client; | jack_client_internal_t *client; | ||||
jack_client_control_t *ctl; | jack_client_control_t *ctl; | ||||
JSList *node; | JSList *node; | ||||
char c; | |||||
int status; | int status; | ||||
char c; | |||||
float delayed_usecs; | float delayed_usecs; | ||||
unsigned long long now, then; | unsigned long long now, then; | ||||
c = get_cycles(); | |||||
engine->process_errors = 0; | engine->process_errors = 0; | ||||
for (node = engine->clients; node; node = jack_slist_next (node)) { | for (node = engine->clients; node; node = jack_slist_next (node)) { | ||||
@@ -522,7 +520,7 @@ jack_process (jack_engine_t *engine, jack_nframes_t nframes) | |||||
/* external subgraph */ | /* external subgraph */ | ||||
ctl->state = Triggered; // a race exists if we do this after the write(2) | ctl->state = Triggered; // a race exists if we do this after the write(2) | ||||
ctl->signalled_at = get_cycles(); | |||||
ctl->signalled_at = jack_get_microseconds(); | |||||
ctl->awake_at = 0; | ctl->awake_at = 0; | ||||
ctl->finished_at = 0; | ctl->finished_at = 0; | ||||
@@ -536,7 +534,7 @@ jack_process (jack_engine_t *engine, jack_nframes_t nframes) | |||||
break; | break; | ||||
} | } | ||||
then = get_cycles (); | |||||
then = jack_get_microseconds (); | |||||
if (engine->asio_mode) { | if (engine->asio_mode) { | ||||
engine->driver->wait (engine->driver, client->subgraph_wait_fd, &status, &delayed_usecs); | engine->driver->wait (engine->driver, client->subgraph_wait_fd, &status, &delayed_usecs); | ||||
@@ -569,19 +567,19 @@ jack_process (jack_engine_t *engine, jack_nframes_t nframes) | |||||
} | } | ||||
} | } | ||||
now = get_cycles(); | |||||
now = jack_get_microseconds (); | |||||
if (status != 0) { | if (status != 0) { | ||||
if (engine->verbose) { | if (engine->verbose) { | ||||
fprintf (stderr, "at %Lu client waiting on %d took %.9f usecs, status = %d sig = %Lu awa = %Lu fin = %Lu dur=%.6f\n", | |||||
fprintf (stderr, "at %Lu client waiting on %d took %Lu usecs, status = %d sig = %Lu awa = %Lu fin = %Lu dur=%Lu\n", | |||||
now, | now, | ||||
client->subgraph_wait_fd, | client->subgraph_wait_fd, | ||||
(float) (now - then) / engine->cpu_mhz, | |||||
now - then, | |||||
status, | status, | ||||
ctl->signalled_at, | ctl->signalled_at, | ||||
ctl->awake_at, | ctl->awake_at, | ||||
ctl->finished_at, | ctl->finished_at, | ||||
((float) (ctl->finished_at - ctl->signalled_at)) / engine->cpu_mhz); | |||||
ctl->finished_at - ctl->signalled_at); | |||||
} | } | ||||
/* we can only consider the timeout a client error if it actually woke up. | /* we can only consider the timeout a client error if it actually woke up. | ||||
@@ -628,7 +626,7 @@ jack_engine_post_process (jack_engine_t *engine) | |||||
JSList *node; | JSList *node; | ||||
int need_remove = FALSE; | int need_remove = FALSE; | ||||
engine->control->pending_time.cycles = engine->control->current_time.cycles; | |||||
engine->control->pending_time.usecs = engine->control->current_time.usecs; | |||||
engine->control->current_time = engine->control->pending_time; | engine->control->current_time = engine->control->pending_time; | ||||
/* find any clients that need removal due to timeouts, etc. */ | /* find any clients that need removal due to timeouts, etc. */ | ||||
@@ -1590,6 +1588,7 @@ jack_engine_new (int realtime, int rtpriority, int verbose) | |||||
uid_t uid = getuid (); | uid_t uid = getuid (); | ||||
uid_t euid = geteuid (); | uid_t euid = geteuid (); | ||||
#endif | #endif | ||||
jack_init_time (); | |||||
engine = (jack_engine_t *) malloc (sizeof (jack_engine_t)); | engine = (jack_engine_t *) malloc (sizeof (jack_engine_t)); | ||||
@@ -1608,7 +1607,6 @@ jack_engine_new (int realtime, int rtpriority, int verbose) | |||||
engine->silent_buffer = 0; | engine->silent_buffer = 0; | ||||
engine->verbose = verbose; | engine->verbose = verbose; | ||||
engine->asio_mode = FALSE; | engine->asio_mode = FALSE; | ||||
engine->cpu_mhz = jack_get_mhz(); | |||||
jack_engine_reset_rolling_usecs (engine); | jack_engine_reset_rolling_usecs (engine); | ||||
@@ -1843,7 +1841,7 @@ jack_inc_frame_time (jack_engine_t *engine, jack_nframes_t amount) | |||||
time->guard1++; | time->guard1++; | ||||
time->frames += amount; | time->frames += amount; | ||||
time->stamp = get_cycles (); | |||||
time->stamp = jack_get_microseconds (); | |||||
// atomic_inc (&time->guard2, 1); | // atomic_inc (&time->guard2, 1); | ||||
// might need a memory barrier here | // might need a memory barrier here | ||||
@@ -1960,12 +1958,12 @@ jack_main_thread (void *arg) | |||||
break; | break; | ||||
} | } | ||||
cycle_end = get_cycles (); | |||||
cycle_end = jack_get_microseconds (); | |||||
/* store the execution time for later averaging */ | /* store the execution time for later averaging */ | ||||
engine->rolling_client_usecs[engine->rolling_client_usecs_index++] = | engine->rolling_client_usecs[engine->rolling_client_usecs_index++] = | ||||
(float) (cycle_end - engine->control->current_time.cycles) / engine->cpu_mhz; | |||||
cycle_end - engine->control->current_time.usecs; | |||||
if (engine->rolling_client_usecs_index >= JACK_ENGINE_ROLLING_COUNT) { | if (engine->rolling_client_usecs_index >= JACK_ENGINE_ROLLING_COUNT) { | ||||
engine->rolling_client_usecs_index = 0; | engine->rolling_client_usecs_index = 0; | ||||
@@ -40,7 +40,7 @@ | |||||
#include <jack/engine.h> | #include <jack/engine.h> | ||||
#include <jack/pool.h> | #include <jack/pool.h> | ||||
#include <jack/error.h> | #include <jack/error.h> | ||||
#include <jack/cycles.h> | |||||
#include <jack/time.h> | |||||
#include <jack/jslist.h> | #include <jack/jslist.h> | ||||
#include <jack/version.h> | #include <jack/version.h> | ||||
@@ -50,6 +50,8 @@ | |||||
#include <jack/timestamps.h> | #include <jack/timestamps.h> | ||||
#endif /* WITH_TIMESTAMPS */ | #endif /* WITH_TIMESTAMPS */ | ||||
jack_time_t __jack_cpu_mhz; | |||||
char *jack_server_dir = "/tmp"; | char *jack_server_dir = "/tmp"; | ||||
void | void | ||||
@@ -139,7 +141,6 @@ jack_client_alloc () | |||||
client->thread_ok = FALSE; | client->thread_ok = FALSE; | ||||
client->first_active = TRUE; | client->first_active = TRUE; | ||||
client->on_shutdown = NULL; | client->on_shutdown = NULL; | ||||
client->cpu_mhz = (float) jack_get_mhz (); | |||||
return client; | return client; | ||||
} | } | ||||
@@ -449,6 +450,12 @@ jack_client_new (const char *client_name) | |||||
int control_shm_id; | int control_shm_id; | ||||
void *addr; | void *addr; | ||||
/* external clients need this initialized; internal clients | |||||
will use the setup in the server's address space. | |||||
*/ | |||||
jack_init_time (); | |||||
if (jack_request_client (ClientExternal, client_name, "", "", &res, &req_fd)) { | if (jack_request_client (ClientExternal, client_name, "", "", &res, &req_fd)) { | ||||
return NULL; | return NULL; | ||||
} | } | ||||
@@ -654,7 +661,7 @@ jack_client_thread (void *arg) | |||||
*/ | */ | ||||
if (client->pollfd[1].revents & POLLIN) { | if (client->pollfd[1].revents & POLLIN) { | ||||
control->awake_at = get_cycles(); | |||||
control->awake_at = jack_get_microseconds(); | |||||
} | } | ||||
if (client->pollfd[0].revents & ~POLLIN || client->control->dead) { | if (client->pollfd[0].revents & ~POLLIN || client->control->dead) { | ||||
@@ -741,7 +748,7 @@ jack_client_thread (void *arg) | |||||
getpid(), | getpid(), | ||||
control->signalled_at, | control->signalled_at, | ||||
control->awake_at, | control->awake_at, | ||||
((float) (control->awake_at - control->signalled_at))/client->cpu_mhz, | |||||
control->awake_at - control->signalled_at, | |||||
client->pollfd[1].fd); | client->pollfd[1].fd); | ||||
control->state = Running; | control->state = Running; | ||||
@@ -754,7 +761,7 @@ jack_client_thread (void *arg) | |||||
control->state = Finished; | control->state = Finished; | ||||
} | } | ||||
control->finished_at = get_cycles(); | |||||
control->finished_at = jack_get_microseconds(); | |||||
#ifdef WITH_TIMESTAMPS | #ifdef WITH_TIMESTAMPS | ||||
jack_timestamp ("finished"); | jack_timestamp ("finished"); | ||||
@@ -772,7 +779,8 @@ jack_client_thread (void *arg) | |||||
break; | break; | ||||
} | } | ||||
DEBUG ("client sent message to next stage by %Lu, client reading on graph_wait_fd==%d", get_cycles(), client->graph_wait_fd); | |||||
DEBUG ("client sent message to next stage by %Lu, client reading on graph_wait_fd==%d", | |||||
jack_get_microseconds(), client->graph_wait_fd); | |||||
#ifdef WITH_TIMESTAMPS | #ifdef WITH_TIMESTAMPS | ||||
jack_timestamp ("read pending byte from wait"); | jack_timestamp ("read pending byte from wait"); | ||||
@@ -1376,7 +1384,7 @@ jack_frames_since_cycle_start (const jack_client_t *client) | |||||
{ | { | ||||
float usecs; | float usecs; | ||||
usecs = (float) (get_cycles() - client->engine->current_time.cycles) / client->cpu_mhz; | |||||
usecs = jack_get_microseconds() - client->engine->current_time.usecs; | |||||
return (jack_nframes_t) floor ((((float) client->engine->current_time.frame_rate) / 1000000.0f) * usecs); | return (jack_nframes_t) floor ((((float) client->engine->current_time.frame_rate) / 1000000.0f) * usecs); | ||||
} | } | ||||
@@ -1389,7 +1397,7 @@ jack_frame_time (const jack_client_t *client) | |||||
jack_read_frame_time (client, ¤t); | jack_read_frame_time (client, ¤t); | ||||
usecs = (float) (get_cycles() - current.stamp) / client->cpu_mhz; | |||||
usecs = jack_get_microseconds() - current.stamp; | |||||
elapsed = (jack_nframes_t) floor ((((float) client->engine->current_time.frame_rate) / 1000000.0f) * usecs); | elapsed = (jack_nframes_t) floor ((((float) client->engine->current_time.frame_rate) / 1000000.0f) * usecs); | ||||
return current.frames + elapsed; | return current.frames + elapsed; | ||||
@@ -1442,7 +1450,21 @@ jack_set_transport_info (jack_client_t *client, | |||||
return 0; | return 0; | ||||
} | } | ||||
int | |||||
float | |||||
jack_cpu_load (jack_client_t *client) | |||||
{ | |||||
return client->engine->cpu_load; | |||||
} | |||||
pthread_t | |||||
jack_client_thread_id (jack_client_t *client) | |||||
{ | |||||
return client->thread_id; | |||||
} | |||||
#if defined(linux) | |||||
jack_time_t | |||||
jack_get_mhz (void) | jack_get_mhz (void) | ||||
{ | { | ||||
FILE *f = fopen("/proc/cpuinfo", "r"); | FILE *f = fopen("/proc/cpuinfo", "r"); | ||||
@@ -1454,7 +1476,7 @@ jack_get_mhz (void) | |||||
for ( ; ; ) | for ( ; ; ) | ||||
{ | { | ||||
int mhz; | |||||
jack_time_t mhz; | |||||
int ret; | int ret; | ||||
char buf[1000]; | char buf[1000]; | ||||
@@ -1465,9 +1487,9 @@ jack_get_mhz (void) | |||||
} | } | ||||
#ifdef __powerpc__ | #ifdef __powerpc__ | ||||
ret = sscanf(buf, "clock\t: %dMHz", &mhz); | |||||
ret = sscanf(buf, "clock\t: %LuMHz", &mhz); | |||||
#else | #else | ||||
ret = sscanf(buf, "cpu MHz : %d", &mhz); | |||||
ret = sscanf(buf, "cpu MHz : %Lu", &mhz); | |||||
#endif /* __powerpc__ */ | #endif /* __powerpc__ */ | ||||
if (ret == 1) | if (ret == 1) | ||||
@@ -1478,15 +1500,9 @@ jack_get_mhz (void) | |||||
} | } | ||||
} | } | ||||
float | |||||
jack_cpu_load (jack_client_t *client) | |||||
{ | |||||
return client->engine->cpu_load; | |||||
} | |||||
pthread_t | |||||
jack_client_thread_id (jack_client_t *client) | |||||
void jack_init_time () | |||||
{ | { | ||||
return client->thread_id; | |||||
__jack_cpu_mhz = jack_get_mhz (); | |||||
} | } | ||||
#endif |
@@ -22,10 +22,10 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include <jack/timestamps.h> | #include <jack/timestamps.h> | ||||
#include <jack/internal.h> | #include <jack/internal.h> | ||||
#include <jack/cycles.h> | |||||
#include <jack/time.h> | |||||
typedef struct { | typedef struct { | ||||
cycles_t when; | |||||
jack_time_t when; | |||||
const char *what; | const char *what; | ||||
} jack_timestamp_t; | } jack_timestamp_t; | ||||
@@ -49,7 +49,7 @@ void | |||||
jack_timestamp (const char *what) | jack_timestamp (const char *what) | ||||
{ | { | ||||
if (timestamp_index < timestamp_cnt) { | if (timestamp_index < timestamp_cnt) { | ||||
timestamps[timestamp_index].when = get_cycles(); | |||||
timestamps[timestamp_index].when = jack_get_microseconds(); | |||||
timestamps[timestamp_index].what = what; | timestamps[timestamp_index].what = what; | ||||
++timestamp_index; | ++timestamp_index; | ||||
} | } | ||||