git-svn-id: svn+ssh://jackaudio.org/trunk/jack@245 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
| @@ -2,7 +2,7 @@ MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure config.h.in \ | |||
| stamp-h.in config.log config.cache \ | |||
| config.guess mkinstalldirs config.status \ | |||
| missing install-sh config.sub ltconfig \ | |||
| ltmain.sh acinclude.m4 | |||
| ltmain.sh | |||
| if HAVE_DOXYGEN | |||
| DOC_DIR = doc | |||
| @@ -4,8 +4,8 @@ AC_INIT(jackd/jackd.c) | |||
| AC_CONFIG_AUX_DIR(.) | |||
| JACK_MAJOR_VERSION=0 | |||
| JACK_MINOR_VERSION=37 | |||
| JACK_MICRO_VERSION=2 | |||
| JACK_MINOR_VERSION=38 | |||
| JACK_MICRO_VERSION=0 | |||
| BETA= | |||
| @@ -162,15 +162,10 @@ if test $HAVE_FLTK = "false"; then | |||
| AC_MSG_WARN([*** no fltk found, the fltk example client will not be built]) | |||
| fi | |||
| AC_CHECK_LIB(sndfile,main, | |||
| [AC_CHECK_HEADER(sndfile.h, | |||
| [HAVE_SNDFILE=true], | |||
| [HAVE_SNDFILE=false] | |||
| )], | |||
| [HAVE_SNDFILE=false] | |||
| ) | |||
| if test $HAVE_SNDFILE = "false"; then | |||
| AC_MSG_WARN([*** no libsndfile found, the jackrec example client will not be built]) | |||
| HAVE_SNDFILE= | |||
| PKG_CHECK_MODULES(SNDFILE, sndfile >= 1.0,[HAVE_SNDFILE=true], [true]) | |||
| if test x$HAVE_SNDFILE = x; then | |||
| AC_MSG_WARN([*** the jackrec example client will not be built]) | |||
| fi | |||
| # you need doxygen to make dist. | |||
| @@ -867,7 +867,7 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float *delay | |||
| } | |||
| driver->poll_last = poll_ret; | |||
| driver->poll_next = poll_ret + (unsigned long long) floor ((driver->period_usecs * driver->cpu_mhz)); | |||
| driver->engine->control->time.cycles = get_cycles(); | |||
| driver->engine->control->current_time.cycles = get_cycles(); | |||
| } | |||
| /* check to see if it was the extra FD that caused us to return from poll | |||
| @@ -30,6 +30,9 @@ bin_PROGRAMS = jack_simple_client \ | |||
| jack_cache_killer \ | |||
| jack_connect \ | |||
| jack_disconnect \ | |||
| jack_metro \ | |||
| jack_showtime \ | |||
| jack_lsp \ | |||
| $(FLTK_CLIENT) $(JACKREC) | |||
| AM_CFLAGS = -I.. $(JACK_CFLAGS) $(GLIB_CFLAGS) | |||
| @@ -55,6 +58,19 @@ jack_cache_killer_SOURCES = cache_killer.c | |||
| jack_cache_killer_LDFLAGS = -ldl -lpthread | |||
| jack_cache_killer_LDADD = ../libjack/libjack.la | |||
| jack_metro_SOURCES = metro.c | |||
| jack_metro_LDFLAGS = -ldl -lpthread | |||
| jack_metro_LDADD = ../libjack/libjack.la | |||
| jack_lsp_SOURCES = lsp.c | |||
| jack_lsp_LDFLAGS = -ldl -lpthread | |||
| jack_lsp_LDADD = ../libjack/libjack.la | |||
| jack_showtime_SOURCES = showtime.c | |||
| jack_showtime_LDFLAGS = -ldl -lpthread | |||
| jack_showtime_LDADD = ../libjack/libjack.la | |||
| if HAVE_FLTK | |||
| jack_fltk_client_SOURCES = fltk_client.cc | |||
| jack_fltk_client_LDFLAGS = -L/usr/X11R6/lib -lfltk -lX11 -lXext -ldl -lpthread | |||
| @@ -0,0 +1,30 @@ | |||
| #include <stdio.h> | |||
| #include <unistd.h> | |||
| #include <jack/jack.h> | |||
| int | |||
| main (int argc, char *argv[]) | |||
| { | |||
| jack_client_t *client; | |||
| const char **ports; | |||
| int i; | |||
| /* try to become a client of the JACK server */ | |||
| if ((client = jack_client_new ("lsp")) == 0) { | |||
| fprintf (stderr, "jack server not running?\n"); | |||
| return 1; | |||
| } | |||
| ports = jack_get_ports (client, NULL, NULL, 0); | |||
| for (i = 0; ports[i]; ++i) { | |||
| printf ("%s\n", ports[i]); | |||
| } | |||
| jack_client_close (client); | |||
| exit (0); | |||
| } | |||
| @@ -0,0 +1,242 @@ | |||
| /* | |||
| Copyright (C) 2002 Anthony Van Groningen | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include <stdlib.h> | |||
| #include <stdio.h> | |||
| #include <errno.h> | |||
| #include <unistd.h> | |||
| #include <math.h> | |||
| #include <jack/jack.h> | |||
| #include <glib.h> | |||
| #include <getopt.h> | |||
| #include <string.h> | |||
| typedef jack_default_audio_sample_t sample_t; | |||
| const double PI = 3.14; | |||
| jack_client_t *client; | |||
| jack_port_t *output_port; | |||
| unsigned long sr; | |||
| int freq = 880; | |||
| int bpm; | |||
| jack_nframes_t tone_length, wave_length; | |||
| sample_t *wave; | |||
| long pos = 0; | |||
| void | |||
| usage () | |||
| { | |||
| fprintf (stderr, "\ | |||
| usage: jack_metro | |||
| [ --frequency OR -f frequency (in Hz) ] | |||
| [ --amplitude OR -A maximum amplitude (between 0 and 1) ] | |||
| [ --duration OR -D duration (in ms) ] | |||
| [ --attack OR -a attack (in percent of duration) ] | |||
| [ --decay OR -d decay (in percent of duration) ] | |||
| [ --name OR -n jack name for metronome client ] | |||
| --bpm OR -b beats per minute | |||
| "); | |||
| } | |||
| int | |||
| process (jack_nframes_t nframes, void *arg) | |||
| { | |||
| sample_t *buffer = (sample_t *) jack_port_get_buffer(output_port, nframes); | |||
| jack_nframes_t frames_left = nframes; | |||
| while (wave_length - pos < frames_left) { | |||
| memcpy (buffer + (nframes - frames_left), wave + pos, sizeof (sample_t) * (wave_length - pos)); | |||
| frames_left -= wave_length - pos; | |||
| pos = 0; | |||
| } | |||
| if (frames_left > 0) { | |||
| memcpy (buffer + (nframes - frames_left), wave + pos, sizeof (sample_t) * frames_left); | |||
| pos += frames_left; | |||
| } | |||
| return 0; | |||
| } | |||
| int | |||
| buffer_size_change () { | |||
| printf("Buffer size has changed! Exiting...\n"); | |||
| exit(-1); | |||
| } | |||
| int | |||
| sample_rate_change () { | |||
| printf("Sample rate has changed! Exiting...\n"); | |||
| exit(-1); | |||
| } | |||
| int | |||
| main (int argc, char *argv[]) | |||
| { | |||
| sample_t scale; | |||
| int i, attack_length, decay_length; | |||
| double *amp; | |||
| double max_amp = 0.5; | |||
| int option_index; | |||
| int opt; | |||
| int got_bpm = 0; | |||
| int attack_percent = 1, decay_percent = 10, dur_arg = 100; | |||
| char *client_name = 0; | |||
| char *bpm_string = "bpm"; | |||
| int verbose = 0; | |||
| const char *options = "f:A:D:a:d:b:n:hv"; | |||
| struct option long_options[] = | |||
| { | |||
| {"frequency", 1, 0, 'f'}, | |||
| {"amplitude", 1, 0, 'A'}, | |||
| {"duration", 1, 0, 'D'}, | |||
| {"attack", 1, 0, 'a'}, | |||
| {"decay", 1, 0, 'd'}, | |||
| {"bpm", 1, 0, 'b'}, | |||
| {"name", 1, 0, 'n'}, | |||
| {"help", 0, 0, 'h'}, | |||
| {"verbose", 0, 0, 'v'}, | |||
| {0, 0, 0, 0} | |||
| }; | |||
| while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { | |||
| switch (opt) { | |||
| case 'f': | |||
| if ((freq = atoi (optarg)) <= 0) { | |||
| fprintf (stderr, "invalid frequency\n"); | |||
| return -1; | |||
| } | |||
| break; | |||
| case 'A': | |||
| if (((max_amp = atof (optarg)) <= 0)|| (max_amp > 1)) { | |||
| fprintf (stderr, "invalid amplitude\n"); | |||
| return -1; | |||
| } | |||
| break; | |||
| case 'D': | |||
| dur_arg = atoi (optarg); | |||
| fprintf (stderr, "durarg = %lu\n", dur_arg); | |||
| break; | |||
| case 'a': | |||
| if (((attack_percent = atoi (optarg)) < 0) || (attack_percent > 100)) { | |||
| fprintf (stderr, "invalid attack percent\n"); | |||
| return -1; | |||
| } | |||
| break; | |||
| case 'd': | |||
| if (((decay_percent = atoi (optarg)) < 0) || (decay_percent > 100)) { | |||
| fprintf (stderr, "invalid decay percent\n"); | |||
| return -1; | |||
| } | |||
| break; | |||
| case 'b': | |||
| got_bpm = 1; | |||
| if ((bpm = atoi (optarg)) < 0) { | |||
| fprintf (stderr, "invalid bpm\n"); | |||
| return -1; | |||
| } | |||
| bpm_string = (char *) malloc ((strlen (optarg) + 4) * sizeof (char)); | |||
| strcpy (bpm_string, optarg); | |||
| strcat (bpm_string, "_bpm"); | |||
| fprintf (stderr, "bpm = %lu\n", bpm); | |||
| break; | |||
| case 'n': | |||
| client_name = (char *) malloc (strlen (optarg) * sizeof (char)); | |||
| strcpy (client_name, optarg); | |||
| break; | |||
| case 'v': | |||
| verbose = 1; | |||
| break; | |||
| default: | |||
| fprintf (stderr, "unknown option %c\n", opt); | |||
| case 'h': | |||
| usage (); | |||
| return -1; | |||
| } | |||
| } | |||
| if (!got_bpm) { | |||
| fprintf (stderr, "bpm not specified\n"); | |||
| usage (); | |||
| return -1; | |||
| } | |||
| /* Initial Jack setup, get sample rate */ | |||
| if (!client_name) { | |||
| client_name = (char *) malloc (9 * sizeof (char)); | |||
| strcpy (client_name, "metro"); | |||
| } | |||
| if ((client = jack_client_new (client_name)) == 0) { | |||
| fprintf (stderr, "jack server not running?\n"); | |||
| return 1; | |||
| } | |||
| jack_set_process_callback (client, process, 0); | |||
| output_port = jack_port_register (client, bpm_string, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| sr = jack_get_sample_rate (client); | |||
| /* setup wave table parameters */ | |||
| wave_length = 60 * sr / bpm; | |||
| tone_length = sr * dur_arg / 1000; | |||
| attack_length = tone_length * attack_percent / 100; | |||
| decay_length = tone_length * decay_percent / 100; | |||
| scale = 2 * PI * freq / sr; | |||
| if (tone_length >= wave_length) { | |||
| fprintf (stderr, "invalid duration (tone length = %lu, wave length = %lu\n", tone_length, wave_length); | |||
| return -1; | |||
| } | |||
| if (attack_length + decay_length > tone_length) { | |||
| fprintf (stderr, "invalid attack/decay\n"); | |||
| return -1; | |||
| } | |||
| /* Build the wave table */ | |||
| wave = (sample_t *) malloc (wave_length * sizeof(sample_t)); | |||
| amp = (double *) malloc (tone_length * sizeof(double)); | |||
| for (i = 0; i < attack_length; i++) { | |||
| amp[i] = max_amp * i / ((double) attack_length); | |||
| } | |||
| for (i = attack_length; i < tone_length - decay_length; i++) { | |||
| amp[i] = max_amp; | |||
| } | |||
| for (i = tone_length - decay_length; i < tone_length; i++) { | |||
| amp[i] = - max_amp * (i - (double) tone_length) / ((double) decay_length); | |||
| } | |||
| for (i = 0; i < tone_length; i++) { | |||
| wave[i] = amp[i] * sin (scale * i); | |||
| } | |||
| for (i = tone_length; i < wave_length; i++) { | |||
| wave[i] = 0; | |||
| } | |||
| if (jack_activate (client)) { | |||
| fprintf (stderr, "cannot activate client"); | |||
| return 1; | |||
| } | |||
| if (verbose) { | |||
| } | |||
| while (1) { | |||
| sleep(1); | |||
| }; | |||
| } | |||
| @@ -0,0 +1,85 @@ | |||
| #include <stdio.h> | |||
| #include <errno.h> | |||
| #include <unistd.h> | |||
| #include <signal.h> | |||
| #include <jack/jack.h> | |||
| #include <jack/transport.h> | |||
| jack_client_t *client; | |||
| jack_transport_info_t now; | |||
| void | |||
| showtime () | |||
| { | |||
| jack_transport_info_t current = now; | |||
| printf ("frame: %lu state: %d loop: %lu-%lu\n", current.position, current.state, current.loop_start, current.loop_end); | |||
| } | |||
| int | |||
| process (jack_nframes_t nframes, void *arg) | |||
| { | |||
| now.valid = JackTransportState|JackTransportPosition|JackTransportLoop; | |||
| jack_get_transport_info (client, &now); | |||
| return 0; | |||
| } | |||
| void | |||
| jack_shutdown (void *arg) | |||
| { | |||
| exit (1); | |||
| } | |||
| void | |||
| signal_handler (int sig) | |||
| { | |||
| fprintf (stderr, "signal received, exiting ...\n"); | |||
| jack_client_close (client); | |||
| exit (0); | |||
| } | |||
| int | |||
| main (int argc, char *argv[]) | |||
| { | |||
| /* try to become a client of the JACK server */ | |||
| if ((client = jack_client_new ("showtime")) == 0) { | |||
| fprintf (stderr, "jack server not running?\n"); | |||
| return 1; | |||
| } | |||
| signal (SIGQUIT, signal_handler); | |||
| signal (SIGTERM, signal_handler); | |||
| signal (SIGHUP, signal_handler); | |||
| signal (SIGINT, signal_handler); | |||
| /* tell the JACK server to call `process()' whenever | |||
| there is work to be done. | |||
| */ | |||
| jack_set_process_callback (client, process, 0); | |||
| /* tell the JACK server to call `jack_shutdown()' if | |||
| it ever shuts down, either entirely, or if it | |||
| just decides to stop calling us. | |||
| */ | |||
| jack_on_shutdown (client, jack_shutdown, 0); | |||
| /* tell the JACK server that we are ready to roll */ | |||
| if (jack_activate (client)) { | |||
| fprintf (stderr, "cannot activate client"); | |||
| return 1; | |||
| } | |||
| while (1) { | |||
| usleep (100000); | |||
| showtime (); | |||
| } | |||
| jack_client_close (client); | |||
| exit (0); | |||
| } | |||
| @@ -92,10 +92,11 @@ typedef struct { | |||
| typedef struct { | |||
| jack_time_info_t time; | |||
| jack_time_info_t current_time; | |||
| jack_time_info_t pending_time; | |||
| jack_frame_timer_t frame_timer; | |||
| int in_process; | |||
| jack_nframes_t frames_at_cycle_start; | |||
| jack_nframes_t frames_at_cycle_start; | |||
| pid_t engine_pid; | |||
| unsigned long buffer_size; | |||
| char real_time; | |||
| @@ -103,8 +104,9 @@ typedef struct { | |||
| int has_capabilities; | |||
| float cpu_load; | |||
| unsigned long port_max; | |||
| jack_port_shared_t ports[0]; | |||
| int engine_ok; | |||
| jack_port_shared_t ports[0]; | |||
| } jack_control_t; | |||
| typedef enum { | |||
| @@ -411,9 +411,9 @@ jack_set_buffer_size (jack_engine_t *engine, jack_nframes_t nframes) | |||
| static int | |||
| jack_set_sample_rate (jack_engine_t *engine, jack_nframes_t nframes) | |||
| { | |||
| engine->control->time.frame_rate = nframes; | |||
| engine->control->current_time.frame_rate = nframes; | |||
| engine->control->pending_time.frame_rate = nframes; | |||
| return 0; | |||
| } | |||
| @@ -593,6 +593,11 @@ jack_engine_post_process (jack_engine_t *engine) | |||
| jack_lock_graph (engine); | |||
| /* update timebase */ | |||
| engine->control->pending_time.cycles = engine->control->current_time.cycles; | |||
| engine->control->current_time = engine->control->pending_time; | |||
| /* find any clients that need removal due to timeouts, etc. */ | |||
| for (node = engine->clients; node; node = g_slist_next (node) ) { | |||
| @@ -600,7 +605,7 @@ jack_engine_post_process (jack_engine_t *engine) | |||
| client = (jack_client_internal_t *) node->data; | |||
| ctl = client->control; | |||
| if (ctl->timed_out || (ctl->state > NotTriggered && ctl->state != Finished)) { | |||
| if (ctl->state > NotTriggered && ctl->state != Finished && ctl->timed_out++) { | |||
| client->error = TRUE; | |||
| } | |||
| @@ -625,8 +630,9 @@ jack_engine_post_process (jack_engine_t *engine) | |||
| if (client->error) { | |||
| if (engine->verbose) { | |||
| fprintf (stderr, "removing failed client %s state = %s\n", | |||
| client->control->name, client_state_names[client->control->state]); | |||
| fprintf (stderr, "removing failed client %s state = %s errors = %d\n", | |||
| client->control->name, client_state_names[client->control->state], | |||
| client->error); | |||
| } | |||
| jack_remove_client (engine, (jack_client_internal_t *) node->data); | |||
| @@ -1039,7 +1045,10 @@ jack_client_deactivate (jack_engine_t *engine, jack_client_id_t id) | |||
| if (client == engine->timebase_client) { | |||
| engine->timebase_client = 0; | |||
| engine->control->time.frame = 0; | |||
| engine->control->current_time.frame = 0; | |||
| engine->control->pending_time.frame = 0; | |||
| engine->control->current_time.transport_state = JackTransportStopped; | |||
| engine->control->pending_time.transport_state = JackTransportStopped; | |||
| } | |||
| for (portnode = client->ports; portnode; portnode = g_slist_next (portnode)) { | |||
| @@ -1408,8 +1417,10 @@ jack_engine_new (int realtime, int rtpriority, int verbose) | |||
| engine->control->cpu_load = 0; | |||
| engine->control->buffer_size = 0; | |||
| engine->control->time.frame_rate = 0; | |||
| engine->control->time.frame = 0; | |||
| engine->control->current_time.frame_rate = 0; | |||
| engine->control->current_time.frame = 0; | |||
| engine->control->pending_time.frame_rate = 0; | |||
| engine->control->pending_time.frame = 0; | |||
| engine->control->in_process = 0; | |||
| engine->control->has_capabilities = 0; | |||
| @@ -1675,7 +1686,7 @@ jack_main_thread (void *arg) | |||
| /* store the execution time for later averaging */ | |||
| engine->rolling_client_usecs[engine->rolling_client_usecs_index++] = | |||
| (float) (cycle_end - engine->control->time.cycles) / engine->cpu_mhz; | |||
| (float) (cycle_end - engine->control->current_time.cycles) / engine->cpu_mhz; | |||
| if (engine->rolling_client_usecs_index >= JACK_ENGINE_ROLLING_COUNT) { | |||
| engine->rolling_client_usecs_index = 0; | |||
| @@ -1882,7 +1893,10 @@ jack_remove_client (jack_engine_t *engine, jack_client_internal_t *client) | |||
| if (client == engine->timebase_client) { | |||
| engine->timebase_client = 0; | |||
| engine->control->time.frame = 0; | |||
| engine->control->current_time.frame = 0; | |||
| engine->control->pending_time.frame = 0; | |||
| engine->control->current_time.transport_state = JackTransportStopped; | |||
| engine->control->pending_time.transport_state = JackTransportStopped; | |||
| } | |||
| jack_client_disconnect (engine, client); | |||
| @@ -214,6 +214,8 @@ jack_engine_waiter_thread (void *arg) | |||
| } | |||
| if (warg->argc) { | |||
| fprintf (stderr, "loading driver ..\n"); | |||
| if ((driver = jack_driver_load (warg->argc, warg->argv)) == 0) { | |||
| fprintf (stderr, "cannot load driver module %s\n", warg->argv[0]); | |||
| @@ -228,6 +230,8 @@ jack_engine_waiter_thread (void *arg) | |||
| jack_set_asio_mode (engine, TRUE); | |||
| } | |||
| fprintf (stderr, "starting engine\n"); | |||
| if (jack_run (engine)) { | |||
| fprintf (stderr, "cannot start main JACK thread\n"); | |||
| kill (warg->pid, SIGTERM); | |||
| @@ -1100,7 +1100,7 @@ unsigned long jack_get_buffer_size (jack_client_t *client) | |||
| unsigned long jack_get_sample_rate (jack_client_t *client) | |||
| { | |||
| return client->engine->time.frame_rate; | |||
| return client->engine->current_time.frame_rate; | |||
| } | |||
| static jack_port_t * | |||
| @@ -1513,7 +1513,7 @@ jack_set_sample_rate_callback (jack_client_t *client, JackSampleRateCallback cal | |||
| /* Now invoke it */ | |||
| callback (client->engine->time.frame_rate, arg); | |||
| callback (client->engine->current_time.frame_rate, arg); | |||
| return 0; | |||
| } | |||
| @@ -1780,8 +1780,8 @@ jack_frames_since_cycle_start (const jack_client_t *client) | |||
| { | |||
| float usecs; | |||
| usecs = (float) (get_cycles() - client->engine->time.cycles) / client->cpu_mhz; | |||
| return (jack_nframes_t) floor ((((float) client->engine->time.frame_rate) / 1000000.0f) * usecs); | |||
| usecs = (float) (get_cycles() - client->engine->current_time.cycles) / client->cpu_mhz; | |||
| return (jack_nframes_t) floor ((((float) client->engine->current_time.frame_rate) / 1000000.0f) * usecs); | |||
| } | |||
| jack_nframes_t | |||
| @@ -1794,7 +1794,7 @@ jack_frame_time (const jack_client_t *client) | |||
| jack_read_frame_time (client, ¤t); | |||
| usecs = (float) (get_cycles() - current.stamp) / client->cpu_mhz; | |||
| elapsed = (jack_nframes_t) floor ((((float) client->engine->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; | |||
| } | |||
| @@ -1940,8 +1940,8 @@ int | |||
| jack_get_transport_info (jack_client_t *client, | |||
| jack_transport_info_t *info) | |||
| { | |||
| jack_time_info_t *time_info = &client->engine->time; | |||
| jack_time_info_t *time_info = &client->engine->current_time; | |||
| if (info->valid & JackTransportState) { | |||
| info->state = time_info->transport_state; | |||
| } | |||
| @@ -1962,7 +1962,7 @@ int | |||
| jack_set_transport_info (jack_client_t *client, | |||
| jack_transport_info_t *info) | |||
| { | |||
| jack_time_info_t *time_info = &client->engine->time; | |||
| jack_time_info_t *time_info = &client->engine->pending_time; | |||
| if (info->valid & JackTransportState) { | |||
| time_info->transport_state = info->state; | |||