LIBCW(3)

πŸ“¦
version 3.6.1 Β· 2 versions
, in debian trixie, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, ubuntu questing, ubuntu resolute, ubuntu stonking

🌈 LIBCW β€” the libcw manual, section 3 πŸ’…

okay bestie, buckle up, we're doing the whole libcw page, and it's a long one so we're going in parts. this is part 1 and it's giving encyclopedia but make it cute. πŸŽ€


✨ NAME ✨

libcw β€” general purpose Morse code functions library πŸ¦‹


✨ SYNOPSIS ✨

#include <libcw.h>

int cw_generator_new(int audio_system, const char *device)
void cw_generator_delete(void)
int cw_generator_start(void)
void cw_generator_stop(void)
int cw_set_send_speed(int new_value)
int cw_set_frequency(int new_value)
int cw_set_volume(int new_value)
int cw_set_gap(int new_value)
int cw_set_weighting(int new_value)
int cw_get_send_speed(void)
int cw_get_frequency(void)
int cw_get_volume(void)
int cw_get_gap(void)
int cw_get_weighting(void)
void cw_get_send_parameters(int *dot_usecs, int *dash_usecs,
                            int *end_of_element_usecs,
                            int *end_of_character_usecs, int *end_of_word_usecs,
                            int *additional_usecs, int *adjustment_usecs)
int cw_send_dot(void)
int cw_send_dash(void)
int cw_send_character_space(void)
int cw_send_word_space(void)
int cw_send_representation(const char *representation)
int cw_send_representation_partial(const char *representation)
int cw_send_character(char c)
int cw_send_character_partial(char c)
int cw_send_string(const char *string)
void cw_reset_send_receive_parameters(void)
const char *cw_get_console_device(void)
const char *cw_get_soundcard_device(void)
const char *cw_generator_get_audio_system_label(void)
int cw_generator_remove_last_character(void)
int cw_register_tone_queue_low_callback(void (*callback_func)(void*),
                                        void *callback_arg, int level)
bool cw_is_tone_busy(void)
int cw_wait_for_tone(void)
int cw_wait_for_tone_queue(void)
int cw_wait_for_tone_queue_critical(int level)
bool cw_is_tone_queue_full(void)
int cw_get_tone_queue_capacity(void)
int cw_get_tone_queue_length(void)
void cw_flush_tone_queue(void)
void cw_reset_tone_queue(void)
int cw_queue_tone(int usecs, int frequency)
int cw_set_receive_speed(int new_value)
int cw_get_receive_speed(void)
int cw_set_tolerance(int new_value)
int cw_get_tolerance(void)
void cw_get_receive_parameters(int *dot_usecs, int *dash_usecs,
                               int *dot_min_usecs, int *dot_max_usecs,
                               int *dash_min_usecs, int *dash_max_usecs,
                               int *end_of_element_min_usecs,
                               int *end_of_element_max_usecs,
                               int *end_of_element_ideal_usecs,
                               int *end_of_character_min_usecs,
                               int *end_of_character_max_usecs,
                               int *end_of_character_ideal_usecs,
                               int *adaptive_threshold)
int cw_set_noise_spike_threshold(int new_value)
int cw_get_noise_spike_threshold(void)
void cw_get_receive_statistics(double *dot_sd, double *dash_sd,
                               double *element_end_sd, double *character_end_sd)
void cw_reset_receive_statistics(void)
void cw_enable_adaptive_receive(void)
void cw_disable_adaptive_receive(void)
bool cw_get_adaptive_receive_state(void)
int cw_start_receive_tone(const struct timeval *timestamp)
int cw_end_receive_tone(const struct timeval *timestamp)
int cw_receive_buffer_dot(const struct timeval *timestamp)
int cw_receive_buffer_dash(const struct timeval *timestamp)
int cw_receive_representation(const struct timeval *timestamp,
                              /* out */ char *representation,
                              /* out */ bool *is_end_of_word,
                              /* out */ bool *is_error)
int cw_receive_character(const struct timeval *timestamp,
                         /* out */ char *c,
                         /* out */ bool *is_end_of_word,
                         /* out */ bool *is_error)
void cw_clear_receive_buffer(void)
int cw_get_receive_buffer_capacity(void)
int cw_get_receive_buffer_length(void)
void cw_reset_receive(void)
void cw_register_keying_callback(void (*callback_func)(void*, int),
                                 void *callback_arg)
void cw_enable_iambic_curtis_mode_b(void)
void cw_disable_iambic_curtis_mode_b(void)
int cw_get_iambic_curtis_mode_b_state(void)
int cw_notify_keyer_paddle_event(int dot_paddle_state, int dash_paddle_state)
int cw_notify_keyer_dot_paddle_event(int dot_paddle_state)
int cw_notify_keyer_dash_paddle_event(int dash_paddle_state)
void cw_get_keyer_paddles(int *dot_paddle_state, int *dash_paddle_state)
void cw_get_keyer_paddle_latches(int *dot_paddle_latch_state,
                                 int *dash_paddle_latch_state)
bool cw_is_keyer_busy(void)
int cw_wait_for_keyer_element(void)
int cw_wait_for_keyer(void)
void cw_reset_keyer(void)
int cw_notify_straight_key_event(int key_state)
int cw_get_straight_key_state(void)
bool cw_is_straight_key_busy(void)
void cw_reset_straight_key(void)
bool cw_is_alsa_possible(const char * device_name)
bool cw_is_console_possible(const char * device_name)
int cw_get_character_count(void)
void cw_list_characters(char * list)
int cw_get_maximum_representation_length(void)
int cw_lookup_character(char character, char * representation)
char * cw_character_to_representation(int character)
int cw_check_representation(const char * representation)
bool cw_representation_is_valid(const char * representation)
int cw_lookup_representation(const char * representation, char * character)
int cw_representation_to_character(const char * representation)
int cw_get_procedural_character_count(void)
void cw_list_procedural_characters(char * list)
int cw_get_maximum_procedural_expansion_length(void)
int cw_lookup_procedural_character(char character, char *expansion,
                                   int * is_usually_expanded)
int cw_get_maximum_phonetic_length(void)
int cw_lookup_phonetic(char character, char * phonetic)
bool cw_character_is_valid(char character)
int cw_check_character(char character)
bool cw_string_is_valid(const char * string)
int cw_check_string(const char * string)
void cw_set_debug_flags(uint32_t flags)
void cw_debug_set_flags(cw_debug_t * debug_object, uint32_t flags)
uint32_t cw_get_debug_flags(void)
uint32_t cw_debug_get_flags(const cw_debug_t * debug_object)
bool cw_debug_has_flag(const cw_debug_t * debug_object, uint32_t flag)
int cw_generator_set_tone_slope(cw_gen_t * gen, int slope_shape,
                                int slope_duration)
bool cw_is_null_possible(__attribute__((unused)) const char * device_name)
bool cw_is_oss_possible(const char * device_name)
bool cw_is_pa_possible(const char * device_name)
void cw_block_callback(int block)
int cw_register_signal_handler(int signal_number, void (*callback_func)(int))
int cw_unregister_signal_handler(int signal_number)
int cw_version(void)
void cw_license(void)
const char * cw_get_audio_system_label(int sound_system)
void cw_get_speed_limits(int * min_speed, int * max_speed)
void cw_get_frequency_limits(int * min_frequency, int * max_frequency)
void cw_get_volume_limits(int * min_volume, int * max_volume)
void cw_get_gap_limits(int * min_gap, int * max_gap)
void cw_get_tolerance_limits(int * min_tolerance, int * max_tolerance)
void cw_get_weighting_limits(int * min_weighting, int * max_weighting)
void cw_complete_reset(void)

like. bestie. look at that list. it's huge. it ate and left no crumbs πŸ’… and every single one of those is real, we're covering all of them, no skips. πŸ”₯


πŸ“– DESCRIPTION πŸ“–

libcw is a general purpose CW (Morse code) functions library. πŸ¦‹ it's got routines for converting characters into Morse code representations and back again, for sending Morse code characters, and for receiving characters. it also has routines to emulate an Iambic Morse keyer and a straight key. iconic behavior honestly.

you can drop this library into any program that wants these features β€” it's literally built to be included. and get this: it forms the heart of three Morse code tutor applications that come along with the package it's distributed in. main character energy fr fr πŸ‘‘

also go read the cw(7) man page for the info on Morse code timings, plus the dot and dash representations for the various Morse characters. iykyk ✨


🎡 TONE QUEUE 🎡

libcw has an inbuilt tone queue. ✨ the queue gets emptied by background processing, using SIGALRM calls and itimers, so your caller program can keep doing other stuff while the library sends tones and keys any external device. multitasking queen πŸ’…

and it's not just the library's own functions that use it β€” the functions that sound Morse code characters and provide a keyer sidetone use it, and the primitive tone queue functions are publicly available to caller programs too. sharing is caring 🫢


πŸŽ›οΈ CONTROLLING AN EXTERNAL DEVICE πŸŽ›οΈ

you can pass libcw the address of a function that controls external keying. this function gets called every single time the library changes the keying state β€” whether that's from sending a Morse character or representation, or from an iambic keyer or straight key state change. πŸ‘‘

the argument passed is a single integer: TRUE for key-down, and FALSE for key-up.

🫢 heads up bestie: libcw calls the external keying function only when the keying state changes. and a call is likely each time a tone is taken off the tone queue.

πŸ“€ SENDING CW CHARACTERS AND STRINGS πŸ“€

libcw offers several functions that send individual characters and character strings as Morse code. it also offers functions that let you send specialized 'representations' β€” and a 'representation' is an ASCII string that consists of only the characters '.' and '-'. no cap. πŸŽ€

so here's the vibe: characters and strings get converted into representations, and then the correct tones for the dots and dashes in those representations get queued on the tone queue, for action by the background queue emptying process. it's a whole pipeline and it's gorgeous 🌸


πŸ“₯ RECEIVING CW CHARACTERS AND REPRESENTATIONS πŸ“₯

libcw contains functions that let it receive Morse code. to receive, the library must be told when a tone start is detected, and when a tone end is detected. πŸ‘€

then it figures out whether that tone was a dot or a dash depending on the timing difference between the two. after the required silence gap has passed, you may query the library to see what the received representation or character was. πŸ¦‹

and errors in receiving? those get detected by means of the flags passed back on the receive character functions. so yeah, you'll know. 😭


πŸ•ΉοΈ IAMBIC KEYER πŸ•ΉοΈ

libcw offers functions to simulate an Iambic Morse keyer. the caller program needs to tell the library about paddle state changes. ✨

πŸ’€ IMPORTANT: Iambic keyer functions are mutually exclusive with character send and straight key functions. pick a lane bestie.

πŸ”‘ STRAIGHT KEY πŸ”‘

libcw offers simple functions to allow effective pass-through of straight key information. the caller program needs to tell the library about key state changes. 🌈

πŸ™ˆ ALSO IMPORTANT: Straight key functions are mutually exclusive with character send and iambic keyer functions. same energy as above, respect the boundaries.

βœ… RETURN CODES βœ…

some of the library's functions return a return code of type int. this return code has two values, as defined in libcw.h: CW_SUCCESS or CW_FAILURE.

and the best part: those two symbolic constants are guaranteed to be identical to boolean true and false. so you can trust them with your whole heart πŸ’–


πŸŽ€ FUNCTIONS πŸŽ€

okay bestie, here's the whole menu of stuff a libcw caller can actually call. every single one, no skips πŸ’–


✨ int cw_generator_new(int audio_system, const char *device)

Brief: Create new generator

Allocates memory for a brand new generator data structure and sets up the default values for some of the generator's properties. Heads up tho: this function does not start the generator β€” so it does not produce a sound. For that you gotta call cw_generator_start(). πŸ’…

Also, notice that the function doesn't return a generator variable. There is at most one generator variable at any given time. You can't have two generators. In some future version of the library the function will return a pointer to the newly allocated generator, and then you could have as many of them as you want β€” but not yet. πŸ™ˆ

audio_system can be one of the following: NULL, console, OSS, ALSA, PulseAudio, soundcard. See "enum cw_audio_systems" in libcw.h for the exact names of the symbolic constants.

  • Parameter: audio_system β€” audio system to be used by the generator
  • Parameter: device β€” name of audio device to be used; if NULL then the library will use the default device.

✨ void cw_generator_delete(void)

Brief: Deallocate generator

Deallocates/destroys the generator data structure that was created with a call to cw_generator_new(). After you call this function you can't start nor use the generator. it's gone, bestie, periodt. πŸ’€


✨ int cw_generator_start(void)

Brief: Start a generator

Starts producing tones using the generator created with cw_generator_new(). The source of tones is a tone queue that's associated with the generator. If the tone queue is empty, the generator will just vibe there and wait for new tones to be queued. πŸ¦‹

  • Returns: CW_FAILURE on errors
  • Returns: CW_SUCCESS on success

✨ void cw_generator_stop(void)

Brief: Shut down a generator

Silences the tone generated by the generator (the level of the generated sine wave is set to zero, with a falling slope 🌊) and shuts the generator down.

The shutdown does not erase the generator's configuration. ✨

If you want to have this generator running again, you have to call cw_generator_start().


✨ int cw_set_send_speed(int new_value)

Brief: Set sending speed of generator

See libcw.h/CW_SPEED_{INITIAL|MIN|MAX} for the initial/minimal/maximal value of send speed.

errno is set to EINVAL if new_value is out of range.

  • Parameter: new_value β€” new value of send speed to be assigned to the generator
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

✨ int cw_set_frequency(int new_value)

Brief: Set frequency of generator

Sets the frequency of the sound wave generated by the generator. The frequency must be within the limits marked by CW_FREQUENCY_MIN and CW_FREQUENCY_MAX.

See libcw.h/CW_FREQUENCY_{INITIAL|MIN|MAX} for the initial/minimal/maximal value of frequency.

errno is set to EINVAL if new_value is out of range.

  • Parameter: new_value β€” new value of frequency to be assigned to the generator
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

✨ int cw_set_volume(int new_value)

Brief: Set volume of generator

Sets the volume of the sound wave generated by the generator. The volume must be within the limits marked by CW_VOLUME_MIN and CW_VOLUME_MAX.

Note that volume settings are not fully possible for the console speaker. In that case, volume settings greater than zero indicate that the console speaker sound is on, and setting the volume to zero will turn the console speaker sound off. πŸ‘‘

See libcw.h/CW_VOLUME_{INITIAL|MIN|MAX} for the initial/minimal/maximal value of volume. errno is set to EINVAL if new_value is out of range.

  • Parameter: new_value β€” new value of volume to be assigned to the generator
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

✨ int cw_set_gap(int new_value)

Brief: Set sending gap of generator

See libcw.h/CW_GAP_{INITIAL|MIN|MAX} for the initial/minimal/maximal value of gap. errno is set to EINVAL if new_value is out of range.

Notice that this function also sets the same gap value for the library's receiver. two for one, slay. 🫢

  • Parameter: new_value β€” new value of gap to be assigned to the generator
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

✨ int cw_set_weighting(int new_value)

Brief: Set sending weighting for generator

See libcw.h/CW_WEIGHTING_{INITIAL|MIN|MAX} for the initial/minimal/maximal value of weighting. errno is set to EINVAL if new_value is out of range.

  • Parameter: new_value β€” new value of weighting to be assigned for the generator
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

✨ int cw_get_send_speed(void)

Brief: Get sending speed from generator

  • Returns: current value of the generator's send speed

✨ int cw_get_frequency(void)

Brief: Get frequency from generator

This function returns the "frequency" parameter of the generator, even if the generator is stopped, or even if the volume of the generated sound is zero.

  • Returns: current value of the generator's frequency

✨ int cw_get_volume(void)

Brief: Get sound volume from generator

This function returns the "volume" parameter of the generator, even if the generator is stopped.

  • Returns: current value of the generator's sound volume

✨ int cw_get_gap(void)

Brief: Get sending gap from generator

  • Returns: current value of the generator's sending gap

✨ int cw_get_weighting(void)

Brief: Get sending weighting from generator

  • Returns: current value of the generator's sending weighting

✨ void cw_get_send_parameters(int *dot_usecs, int *dash_usecs, int *end_of_element_usecs, int *end_of_character_usecs, int *end_of_word_usecs, int *additional_usecs, int *adjustment_usecs)

Brief: Get timing parameters for sending

Returns the low-level timing parameters calculated from the speed, gap, tolerance, and weighting that are set. The parameter values are returned in microseconds. ⏱️

Use NULL for the pointer argument to any parameter value you don't need. (the "not me, I'm just here for the vibes" treatment 😌)

  • Parameter: dot_usecs
  • Parameter: dash_usecs
  • Parameter: end_of_element_usecs
  • Parameter: end_of_character_usecs
  • Parameter: end_of_word_usecs
  • Parameter: additional_usecs
  • Parameter: adjustment_usecs

✨ int cw_send_dot(void)

Brief: Low-level primitive for sending a Dot Mark

Low-level primitive function able to play/send a single Dot Mark. The function appends to a tone queue a normal inter-mark-space after the Dot Mark. πŸ”₯

  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

✨ int cw_send_dash(void)

Brief: Low-level primitive for sending a Dash Mark

Low-level primitive function able to play/send a single Dash Mark. The function appends to a tone queue a normal inter-mark-space after the Dash Mark.

  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

✨ int cw_send_character_space(void)

This function enqueues a space of a specific length: together with the previously implicitly enqueued inter-mark-space of size 1 Unit, enqueueing this space will form a full inter-character-space of size 3 Units. 🧚

  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

✨ int cw_send_word_space(void)

This function enqueues a space of a specific length: together with the previously implicitly enqueued inter-mark-space of size 1 Unit and the implicitly or explicitly enqueued inter-character-space, enqueueing this space will form a full inter-word-space of size 7 Units.

  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

✨ int cw_send_representation(const char *representation)

Brief: Check, then send the given string as dots and dashes.

The representation passed in is assumed to be a complete Morse character; that is, all post-character delays will be added when the character is sent.

On success, the routine returns CW_SUCCESS. On failure, it returns CW_FAILURE, with errno set to:

  • EINVAL if any character of the representation is invalid
  • EBUSY if the sound card, console speaker, or keying system is busy
  • EAGAIN if the tone queue is full, or if there is insufficient space to queue the tones or the representation
  • Parameter: representation β€” representation to send
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

✨ int cw_send_representation_partial(const char *representation)

Brief: Check, then send the given string as dots and dashes

The representation passed in is assumed to be only part of a larger Morse representation; that is, no post-character delays will be added when the character is sent.

On success, the routine returns CW_SUCCESS. On failure, it returns CW_FAILURE, with errno set to:

  • EINVAL if any character of the representation is invalid
  • EBUSY if the sound card, console speaker, or keying system is busy
  • EAGAIN if the tone queue is full, or if there is insufficient space to queue the tones for the representation

✨ int cw_send_character(char c)

Brief: Look up and send a given ASCII character as Morse

The end of character delay is appended to the Morse sent.

On success the routine returns CW_SUCCESS. On failure the function returns CW_FAILURE and sets errno. 😭

errno is set to ENOENT if the given character c is not a valid Morse character. errno is set to EBUSY if the current audio sink or keying system is busy. errno is set to EAGAIN if the generator's tone queue is full, or if there is insufficient space to queue the tones for the character.

This routine returns as soon as the character has been successfully queued for sending; that is, almost immediately. The actual sending happens in background processing. See cw_wait_for_tone() and cw_wait_for_tone_queue() for ways to check the progress of sending. πŸ‘‘

  • Parameter: c β€” character to send
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

✨ int cw_send_character_partial(char c)

Brief: Look up and send a given ASCII character as Morse code

"partial" means that the inter-character-space is not appended to the Morse code sent by the function, to support the formation of combination characters.

On success the function returns CW_SUCCESS. On failure the function returns CW_FAILURE and sets errno.

errno is set to ENOENT if the given character c is not a valid Morse character. errno is set to EBUSY if the audio sink or keying system is busy. errno is set to EAGAIN if the tone queue is full, or if there is insufficient space to queue the tones for the character.

This routine queues its arguments for background processing. See cw_wait_for_tone() and cw_wait_for_tone_queue() for ways to check the progress of sending. 🌸

  • Parameter: c β€” character to send
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

✨ int cw_send_string(const char *string)

Brief: Send a given ASCII string in Morse code

errno is set to ENOENT if any character in the string is not a valid Morse character.

errno is set to EBUSY if the audio sink or keying system is busy.

okay so real talk bestie, continuing where we left off πŸ’…

errno gets set to EAGAIN if the tone queue is full, or if the tone queue runs out of space <em>part way through</em> queueing the string. and here's the messy part β€” an indeterminate number of the characters from the string will have <em>already</em> been queued. so like, it's half-done and nobody knows how half 🫠

for safety, clients can make sure the tone queue is empty before queueing a string, or use cw_send_character() if they need finer control. that's the move fr fr.

this routine queues its arguments for background processing, and the actual sending happens in background processing. see cw_wait_for_tone() and cw_wait_for_tone_queue() for ways to check the progress of sending. πŸ‘€

  • Parameter: string β€” string to send
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

void cw_reset_send_receive_parameters(void)

Brief: Reset send/receive parameters

this one's the factory reset button πŸ’– it resets the library speed, frequency, volume, gap, tolerance, weighting, adaptive receive, and noise spike threshold back to their initial default values, which are: send/receive speed 12 WPM, volume 70 %, frequency 800 Hz, gap 0 dots, tolerance 50 %, and weighting 50 %. iconic defaults, no notes.


const char *cw_get_console_device(void)

Brief: Return char string with console device path

the returned pointer is owned by the library, so don't you dare free it bestie πŸ™ˆ

  • Returns: char string with current console device path

const char *cw_get_soundcard_device(void)

Brief: Return char string with soundcard device name/path

same deal β€” returned pointer is owned by the library 🫢

  • Returns: char string with current soundcard device name or device path

const char *cw_generator_get_audio_system_label(void)

Brief: Get a readable label of current audio system

this one returns one of the following strings: None, Null, Console, OSS, ALSA, PulseAudio, Soundcard. that's the whole menu, bestie πŸŽ€

  • Returns: audio system's label

int cw_generator_remove_last_character(void)

Brief: Remove last character from queue of already enqueued characters

if the character is not actually played by sound sink yet, the library may be able to remove the character. the character's Dots and Dashes won't be played. it's giving undo button energy ✨

this function may be useful if user presses backspace in UI to remove/undo a character.

okay so listen πŸ‘‘ if your application doesn't enqueue whole characters or strings of characters but is using low-level cw_send_dot()/cw_send_dash() functions to enqueue individual Marks, don't use this function. this function won't be able to recognize whole characters and is likely to remove more tones than expected. that's not a vibe, that's a bug in your app.
  • Returns: CW_SUCCESS if function managed to remove a last character before it has been played
  • Returns: CW_FAILURE otherwise

int cw_register_tone_queue_low_callback(void (*callback_func)(void*), void *callback_arg, int level)

Brief: Register callback for low queue state

register a function to be called automatically by the dequeue routine whenever the count of tones in tone queue falls to a given level. to be more precise: the callback is called by queue's dequeue function if, after dequeueing a tone, the function notices that tone queue length has become equal or less than level. so it's a "hey bestie we're running low" ping πŸ¦‹

  • level can't be negative.
  • level can't be equal to or larger than tone queue capacity.
  • if level is zero, the behaviour of the mechanism is not guaranteed to work correctly.
  • if callback_func is NULL then the mechanism becomes disabled.

callback_arg will be passed to callback_arg.

errno is set to EINVAL when level is invalid.

  • Parameter: callback_func β€” callback function to be registered
  • Parameter: callback_arg β€” argument for callback_func to pass return value
  • Parameter: level β€” low level of queue triggering callback call
  • Returns: CW_SUCCESS on successful registration
  • Returns: CW_FAILURE on failure

bool cw_is_tone_busy(void)

Brief: Check if tone sender is busy

indicate if the tone sender is busy. vibe check on the tone sender πŸ’€

  • Returns: true if there are still entries in the tone queue
  • Returns: false if the queue is empty

int cw_wait_for_tone(void)

Brief: Wait for the current tone to complete

  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

int cw_wait_for_tone_queue(void)

Brief: Wait for the tone queue to drain

notice that generator must be running (started with cw_generator_start()) when this function is called, otherwise it will be waiting forever for a change of tone queue's level that will never happen. forever-forever. no cap. 😭
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

int cw_wait_for_tone_queue_critical(int level)

Brief: Wait for the tone queue to drain until only as many tones as given in level remain queued

this routine is for use by programs that want to optimize themselves to avoid the cleanup that happens when the tone queue drains completely; such programs have a short time in which to add more tones to the queue. main character optimization energy, honestly πŸ’…

notice that generator must be running (started with cw_generator_start()) when this function is called, otherwise it will be waiting forever for a change of tone queue's level that will never happen.

if level is negative, function sets errno to EINVAL and returns CW_FAILURE.

  • Parameter: level β€” low level in queue, at which to return
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

bool cw_is_tone_queue_full(void)

Brief: Indicate if the tone queue is full

  • Returns: true if tone queue is full
  • Returns: false if tone queue is not full

int cw_get_tone_queue_capacity(void)

Brief: Return the number of entries the tone queue can accommodate


int cw_get_tone_queue_length(void)

Brief: Return the number of entries currently pending in the tone queue


void cw_flush_tone_queue(void)

Brief: Cancel all pending queued tones, and return to silence.

if there is a tone in progress, the function will wait until this last one has completed, then silence the tones. polite and thorough πŸŽ€


void cw_reset_tone_queue(void)

cancel all pending queued tones, reset any queue low callback registered, and return to silence. this function is suitable for calling from an application exit handler. perfect lil goodbye routine 🫢


int cw_queue_tone(int usecs, int frequency)

Brief: Primitive access to simple tone generation

this routine queues a tone of given duration and frequency. the routine returns CW_SUCCESS on success. if usec or frequency are invalid, it returns CW_FAILURE with errno set to EINVAL. if the sound card, console speaker, or keying function are busy, it returns CW_FAILURE with errno set to EBUSY. if the tone queue is full, it returns false with errno set to EAGAIN. lowkey a whole mood board of return values πŸ’€

  • Parameter: usec β€” duration of queued tone, in microseconds
  • Parameter: frequency β€” frequency of queued tone
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

int cw_set_receive_speed(int new_value)

Brief: Set receiving speed of receiver

see documentation of cw_set_send_speed() for more information.

see libcw.h/CW_SPEED_{INITIAL|MIN|MAX} for initial/minimal/maximal value of receive speed. errno is set to EINVAL if new_value is out of range. errno is set to EPERM if adaptive receive speed tracking is enabled. (can't set it manually while the library's doing its adaptive thing, bestie, that's the rules ✨)

  • Parameter: new_value β€” new value of receive speed to be assigned to receiver
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

int cw_get_receive_speed(void)

Brief: Get receiving speed from receiver

  • Returns: current value of the receiver's receive speed

int cw_set_tolerance(int new_value)

Brief: Set tolerance for receiver

see libcw.h/CW_TOLERANCE_{INITIAL|MIN|MAX} for initial/minimal/maximal value of tolerance. errno is set to EINVAL if new_value is out of range.

  • Parameter: new_value β€” new value of tolerance to be assigned to receiver
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

int cw_get_tolerance(void)

Brief: Get tolerance from receiver

  • Returns: current value of receiver's tolerance

void cw_get_receive_parameters(...)

Brief: Get timing parameters for receiving, and adaptive threshold

void cw_get_receive_parameters(int *dot_usecs, int *dash_usecs,
                            int *dot_min_usecs, int *dot_max_usecs,
                            int *dash_min_usecs, int *dash_max_usecs,
                            int *end_of_element_min_usecs,
                            int *end_of_element_max_usecs,
                            int *end_of_element_ideal_usecs,
                            int *end_of_character_min_usecs,
                            int *end_of_character_max_usecs,
                            int *end_of_character_ideal_usecs,
                            int *adaptive_threshold)

return the low-level timing parameters calculated from the speed, gap, tolerance, and weighting set. parameter values are returned in microseconds. ⏱️

use NULL for the pointer argument to any parameter value not required. so you only grab the ones you actually want, slay.

  • Parameter: dot_usecs
  • Parameter: dash_usecs
  • Parameter: dot_min_usecs
  • Parameter: dot_max_usecs
  • Parameter: dash_min_usecs
  • Parameter: dash_max_usecs
  • Parameter: end_of_element_min_usecs
  • Parameter: end_of_element_max_usecs
  • Parameter: end_of_element_ideal_usecs
  • Parameter: end_of_character_min_usecs
  • Parameter: end_of_character_max_usecs
  • Parameter: end_of_character_ideal_usecs
  • Parameter: adaptive_threshold

int cw_set_noise_spike_threshold(int new_value)

Brief: Set noise spike threshold for receiver

set the period shorter than which, on receive, received marks are ignored. this allows the "receive mark" functions to apply noise canceling for very short apparent marks. for useful results the value should never exceed the dot length of a dot at maximum speed: 20000 microseconds (the dot length at 60WPM). setting a noise threshold of zero turns off receive mark noise canceling. bye bye noise filtering 🌸

the default noise spike threshold is 10000 microseconds.

errno is set to EINVAL if new_value is out of range.

  • Parameter: new_value β€” new value of noise spike threshold to be assigned to receiver
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

int cw_get_noise_spike_threshold(void)

Brief: Get noise spike threshold from receiver

see documentation of cw_set_noise_spike_threshold() for more information

  • Returns: current value of receiver's threshold

void cw_get_receive_statistics(...)

Brief: Calculate and return receiver's timing statistics

void cw_get_receive_statistics(double *dot_sd, double *dash_sd,
                            double *element_end_sd, double
*character_end_sd)

these statistics may be used to obtain a measure of the accuracy of received CW. the values dot_sd and dot_sd contain the standard deviation of dot and dash lengths from the ideal values, and element_end_sd and element_end_sd the deviations for inter element and inter character spacing. statistics are held for all timings in a 256 element circular buffer. if any statistic cannot be calculated, because no records for it exist, the returned value is 0.0. use NULL for the pointer argument to any statistic not required. data girlies, this one's for you πŸ“ŠπŸ’–

  • Parameter: dot_sd
  • Parameter: dash_sd
  • Parameter: element_end_sd
  • Parameter: character_end_sd

void cw_reset_receive_statistics(void)

Brief: clear the receive statistics buffer πŸ’«

Okay so this one wipes the receive statistics buffer clean β€” like, every single record in it gets removed and the whole thing goes right back to its initial default state. Fresh start, no notes, no history. slay.


void cw_enable_adaptive_receive(void)

Brief: enable adaptive receive speed tracking πŸ¦‹

So here's the tea: if adaptive speed tracking is on, the receive functions will try to automatically adjust the receive speed setting so it matches the speed of the incoming Morse code. If it's off, the receive functions just use fixed speed settings and will outright reject incoming Morse that isn't at the expected speed. no vibes-matching, just strict.

Adaptive speed tracking uses a moving average length of the past N marks as its baseline for tracking speeds. The default state is adaptive speed tracking disabled. πŸ‘‘


void cw_disable_adaptive_receive(void)

Brief: disable adaptive receive speed tracking

Go read the docs for cw_enable_adaptive_receive() for the full picture, bestie. Same info, opposite setting. πŸŽ€


bool cw_get_adaptive_receive_state(void)

Brief: get adaptive receive speed tracking flag

This function returns the state of the "adaptive receive enabled" flag. Again, see cw_enable_adaptive_receive() for more.

Returns: true if adaptive speed tracking is enabled Returns: false otherwise


int cw_start_receive_tone(const struct timeval *timestamp)

Brief: signal beginning of receive mark ✨

You call this at the start of a receive mark. If the timestamp is NULL, then the current timestamp is used as the beginning of the mark.

Your client application should call this function when it has detected that a key is being pressed down (closing a circuit).

On error the function returns CW_FAILURE, with errno set to ERANGE if the call comes directly after another cw_start_receive_tone() call, or if an existing received character hasn't been cleared from the buffer. It sets EINVAL if the timestamp passed in is invalid.

Parameter: timestamp β€” time stamp of "key down" event

Returns: CW_SUCCESS on success Returns: CW_FAILURE otherwise (with errno set)


int cw_end_receive_tone(const struct timeval *timestamp)

Brief: signal end of mark πŸ’…

Your client application should call this when it detects a key being released (opening a circuit).

If the timestamp is NULL, the current time is used as the timestamp of the end of the mark.

On success, this routine adds a dot or a dash to the receiver's representation buffer and returns CW_SUCCESS.

On failure, it returns CW_FAIURE, with errno set to: ERANGE if the call wasn't preceded by a cw_start_receive_tone() call, EINVAL if the timestamp passed in isn't valid, ENOENT if the function can't tell from the duration of the Mark whether it's a Dot or a Dash, ENOMEM if the receiver's representation buffer is full, or EAGAIN if the mark was shorter than the threshold for noise and was therefore ignored.

Parameter: timestamp β€” time stamp of "key up" event

Returns: CW_SUCCESS on success Returns: CW_FAILURE on failure


int cw_receive_buffer_dot(const struct timeval *timestamp)

Brief: add a dot to the receiver's representation buffer πŸ“

Documentation for both cw_receive_buffer_dot() and cw_receive_buffer_dash():

Since we literally can't add a mark to the buffer without any accompanying timing information, these functions accept the timestamp of the "end of mark" event. If the timestamp is NULL, the current timestamp is used instead.

These routines are for client code that has already figured out whether a dot or a dash was received, by some method that isn't calling the routines cw_start_receive_tone() and cw_end_receive_tone().

On success, the relevant mark gets added to the receiver's representation buffer.

On failure, the routines return CW_FAILURE and set errno: ERANGE if preceded by a cw_start_receive_tone() call with no matching cw_end_receive_tone(), or if an error condition currently exists within the receiver's buffer, EINVAL if the timestamp passed in isn't valid, ENOMEM if the receiver's representation buffer is full.

Parameter: timestamp β€” timestamp of "end of dot" event

Returns: CW_SUCCESS on success Returns: CW_FAILURE on failure


int cw_receive_buffer_dash(const struct timeval *timestamp)

Brief: add a dash to the receiver's representation buffer πŸ”₯

See the documentation of cw_receive_buffer_dot() for more info, bestie.

Parameter: timestamp β€” timestamp of "end of dash" event

Returns: CW_SUCCESS on success Returns: CW_FAILURE on failure


int cw_receive_representation(const struct timeval *timestamp, /* out */ char *representation, /* out */ bool *is_end_of_word, /* out */ bool *is_error)

Brief: get the current buffered representation from the receiver's representation buffer πŸ‘‘

On success the function fills in representation with the contents of the current representation buffer and returns CW_SUCCESS.

On failure, it returns CW_FAILURE and sets errno to: ERANGE if not preceded by a cw_end_receive_tone() call, a prior successful cw_receive_representation call, or a prior cw_receive_buffer_dot or cw_receive_buffer_dash. EINVAL if the timestamp passed in is invalid. EAGAIN if the call is made too early to determine whether a complete representation has yet been placed in the buffer β€” that is, less than the inter-character-space duration has elapsed since the last cw_end_receive_tone() or cw_receive_buffer_dot/dash call. And heads up: that EAGAIN is not a hard error, it's just a lil "hey, try to get the representation later" heads-up. πŸ’€

is_end_of_word indicates that the space after the last mark received is longer than the inter-character-space, so it must be qualified as inter-word-space.

is_error indicates that the representation was terminated by an error condition.

The function is called periodically (poll()-like function) by client code, hoping that at some attempt the receiver will be ready to hand over the representation. The attempt succeeds only if the data stream is in the "space" state. To mark the end of the space, client code has to provide a timestamp (or pass a NULL timestamp and the function will grab the time stamp at function call). The receiver needs to know the "end of space" event β€” hence the timestamp parameter.

Parameter: timestamp β€” timestamp of event that ends inter-character-space or inter-word-space Parameter: representation β€” buffer for representation (output parameter) Parameter: is_end_of_word β€” buffer for "is end of word" state (output parameter) Parameter: is_error β€” buffer for "error" state (output parameter)

Returns: CW_SUCCESS on success Returns: CW_FAILURE on failure


int cw_receive_character(const struct timeval *timestamp, /* out */ char *c, /* out */ bool *is_end_of_word, /* out */ bool *is_error)

Brief: get a current character 🌸

This function returns the character currently stored in the receiver's representation buffer.

On success the function returns CW_SUCCESS, and fills c with the contents of the current representation buffer, translated into a character.

On failure the function returns CW_FAILURE, with errno set to:

ERANGE if not preceded by a cw_end_receive_tone() call, a prior successful cw_receive_character() call, or a cw_receive_buffer_dot() or cw_receive_buffer_dash() call. EINVAL if the timestamp passed in is invalid. EAGAIN if the call is made too early to determine whether a complete character has yet been placed in the buffer β€” that is, less than the inter-character-space duration has elapsed since the last cw_end_receive_tone() or cw_receive_buffer_dot/dash call. ENOENT if the character stored in the receiver can't be recognized as valid.

is_end_of_word indicates that the space after the last mark received is longer than the inter-character-space, so it must be qualified as inter-word-space.

is_error indicates that the character was terminated by an error condition.

Parameter: timestamp β€” timestamp of event that ends inter-character-space or inter-word-space Parameter: c β€” buffer for character (output parameter) Parameter: is_end_of_word β€” buffer for "is end of word" state (output parameter) Parameter: is_error β€” buffer for "error" state (output parameter)

Returns: CW_SUCCESS on success Returns: CW_FAILURE on failure


void cw_clear_receive_buffer(void)

Brief: clear receiver's representation buffer 🧚

Clears the receiver's representation buffer and resets the receiver's internal state. This gets the receiver all prepped to receive marks and spaces again.

You must call this routine after successful β€” or terminating β€” cw_receive_representation() or cw_receive_character() calls, to clear the states and prepare the buffer to receive more marks and spaces. don't skip it bestie.

When migrating to libcw2.h, use cw_rec_reset_state() instead of this function. ⭐

int cw_get_receive_buffer_capacity(void)

Brief: get the number of elements (dots/dashes) the receiver's buffer can accommodate

The maximum number of elements written out by cw_receive_representation() is the capacity + 1, and that extra character is the terminating NUL. iykyk. πŸ’œ

Returns: number of elements that can be stored in receiver's representation buffer


int cw_get_receive_buffer_length(void)

Brief: get the number of elements (dots/dashes) currently pending in the cw_receiver's representation buffer

Returns: number of elements in receiver's representation buffer


void cw_reset_receive(void)

Brief: clear receive data 🌈

Clears the receiver's representation buffer, statistics, and any retained receiver's state. This function is suitable for calling from an application exit handler.

When migrating to libcw2.h, use cw_rec_reset_state() and cw_rec_reset_statistics() instead of this function. ⭐

void cw_register_keying_callback(void (*callback_func)(void*, int), void *callback_arg)

Brief: register external callback function for keying πŸ’–

Registers a callback_func function that should be called when the state of a key changes from "key open" to "key closed", or vice-versa.

The first argument passed to the registered callback function is the supplied callback_arg, if any. The second argument passed to the registered callback function is the key state: CW_KEY_STATE_CLOSED (one/true) for "key closed", and CW_KEY_STATE_OPEN (zero/false) for "key open".

Calling this routine with a NULL function address disables keying callbacks. Any callback supplied will be called in signal handler context (??).

Parameter: callback_func β€” callback function to be called on key state changes Parameter: callback_arg β€” first argument to callback_func


void cw_enable_iambic_curtis_mode_b(void)

Brief: enable iambic Curtis mode B πŸŽ€

Okay so boom πŸ’₯ normally, the iambic keying functions emulate Curtis 8044 Keyer mode A. In that mode, when both paddles get pressed together, the last dot or dash being sent on release is completed, and literally nothing else is sent. In mode B, when both paddles are pressed together, the last dot or dash being sent on release is completed, and then an opposite element is also sent. Some operators prefer mode B, but bestie, timing is more critical in that mode. The default mode is Curtis mode A. πŸŽ€


void cw_disable_iambic_curtis_mode_b(void)

Just go read the documentation of cw_enable_iambic_curtis_mode_b() for more information, bestie β€” that's where the lore lives. πŸ’…

int cw_get_iambic_curtis_mode_b_state(void)

Same deal: see the documentation of cw_enable_iambic_curtis_mode_b() for more information.

int cw_notify_keyer_paddle_event(int dot_paddle_state, int dash_paddle_state)

Brief: tell the lib that the iambic keyer's paddles changed state.

This function informs the library that the iambic keyer paddles have changed state. The new paddle states get recorded, and if either one transitions from false to true, the paddle latches, for iambic functions, are also set. πŸ“

On success, the routine returns CW_SUCCESS. On failure, it returns CW_FAILURE, with errno set to EBUSY if the tone queue or the straight key are using the sound card, console speaker, or keying system.

If it's appropriate, this routine starts the keyer functions sending the relevant element. The element send and the timing happen in the background, so this routine returns almost immediately. ⚑ no cap.

  • Parameter: dot_paddle_state
  • Parameter: dash_paddle_state
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

int cw_notify_keyer_dot_paddle_event(int dot_paddle_state)

Brief: change state of dot paddle.

Alter the state of just one of the two iambic keyer paddles. The other paddle state of the paddle pair stays exactly as it was, untouched, unbothered. πŸ’…

See cw_notify_keyer_paddle_event() for details of iambic keyer background processing, and how to check its status.

  • Parameter: dot_paddle_state

int cw_notify_keyer_dash_paddle_event(int dash_paddle_state)

See the documentation of cw_notify_keyer_dot_paddle_event() for more information.

void cw_get_keyer_paddles(int *dot_paddle_state, int *dash_paddle_state)

Brief: get the current saved states of the two paddles.

  • Parameter: dot_paddle_state
  • Parameter: dash_paddle_state

void cw_get_keyer_paddle_latches(int *dot_paddle_latch_state, int *dash_paddle_latch_state)

Brief: get the current states of the paddle latches.

This function returns the current saved states of the two paddle latches. A paddle latch is set to true when the paddle state becomes true, and it gets cleared if the paddle state is false when the element finishes sending. ✨

  • Parameter: dot_paddle_latch_state
  • Parameter: dash_paddle_latch_state

bool cw_is_keyer_busy(void)

Brief: check if a keyer is busy.

  • Returns: true if keyer is busy
  • Returns: false if keyer is not busy

int cw_wait_for_keyer_element(void)

Brief: wait for the end of an element from the keyer.

Waits until the end of the current element, dot or dash, from the keyer. 🫢

  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

int cw_wait_for_keyer(void)

Brief: wait for the current keyer cycle to complete.

  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

void cw_reset_keyer(void)

Brief: reset iambic keyer data.

Clear all latches and paddle states of the iambic keyer, return to Curtis 8044 Keyer mode A, and return to silence. πŸ”‡ This function is suitable for calling from an application exit handler.

int cw_notify_straight_key_event(int key_state)

Brief: inform the library that the straight key has changed state.

This routine returns CW_SUCCESS on success. On error, it returns CW_FAILURE, with errno set to EBUSY if the tone queue or the iambic keyer are using the sound card, console speaker, or keying control system. If key_state indicates no change of state, the call is just ignored. πŸ™ˆ

key_state may be either CW_KEY_STATE_OPEN (false) or CW_KEY_STATE_CLOSED (true).

  • Parameter: key_state β€” state of straight key

int cw_get_straight_key_state(void)

Brief: get the saved state of the straight key.

Returns the current saved state of the straight key.

  • Returns: CW_KEY_STATE_CLOSED (true) if the key is down
  • Returns: CW_KEY_STATE_OPEN (false) if the key is up

bool cw_is_straight_key_busy(void)

Brief: check if the straight key is busy.

This routine is just a pseudonym for cw_get_straight_key_state(), and it exists to fill a hole in the API naming conventions. πŸ’€ iconic honestly.

  • Returns: true if the straight key is busy
  • Returns: false if the straight key is not busy

void cw_reset_straight_key(void)

Brief: clear the straight key state, and return to silence.

This function is suitable for calling from an application exit handler. 🧚

bool cw_is_alsa_possible(const char * device_name)

Brief: check if it's possible to open ALSA output with the given device name.

The check consists of two parts:

  1. whether it's possible to load the ALSA shared library
  2. whether it's possible to open the ALSA device specified by device_name

If it's possible to use ALSA with the given device name, the function leaves the library handle (returned by dlopen()) open and some library function symbols loaded, but it does not leave any ALSA PCM handle open. 🎧

  • Parameter(in): device_name β€” name of ALSA device to be used; if NULL or empty then the function will use the library-default device name.
  • Returns: true if opening ALSA output succeeded
  • Returns: false if opening ALSA output failed

bool cw_is_console_possible(const char * device_name)

Brief: check if it's possible to open console buzzer output.

The function does a test opening and a test writing to the console buzzer device device_name, but it closes it before returning. 🌸

It tests that the given console buzzer device exists, and that it will accept the KIOCSOUND ioctl. It unconditionally returns false on platforms that do not support the KIOCSOUND ioctl.

🚨 The call to ioctl will fail if the calling code doesn't have root privileges.

This is the only place where we ask if KIOCSOUND is defined, so client code must call this function whenever it wants to use console output, as every other function called to perform console operations will happily assume that it is allowed to perform such operations. πŸ™ƒ

  • Parameter(in): device_name β€” name of console buzzer device to be used; if NULL or empty then the function will use the library-default device name.
  • Returns: true if opening console output succeeded
  • Returns: false if opening console output failed

int cw_get_character_count(void)

Brief: return the number of characters present in the main character lookup table.

Returns the number of characters that are known to libcw. That number includes:

  • ASCII 7bit letters
  • numerals
  • punctuation
  • ISO 8859-1 accented characters
  • ISO 8859-2 accented characters
  • non-standard procedural signal extensions to standard CW characters
  • Returns: number of characters known to libcw

void cw_list_characters(char * list)

Brief: get the list of characters present in the character lookup table.

This function provides a string containing all of the characters represented in the library's lookup table. 🌈

The list includes:

  • ASCII 7bit letters
  • numerals
  • punctuation
  • ISO 8859-1 accented characters
  • ISO 8859-2 accented characters
  • non-standard procedural signal extensions to standard CW characters

list should be allocated and managed by the caller. The length of list must be at least one greater than the number of characters represented in the character lookup table, returned by cw_get_character_count(). The string placed in list will be NUL-terminated. βœ‚οΈ

  • Parameter(out): list β€” buffer for the string with all characters

int cw_get_maximum_representation_length(void)

Brief: get the length of the longest representation of characters.

This function returns the string length of the longest representation in the main character lookup table. It is the count of dots and dashes in the longest representation of characters known to libcw (not including the terminating NUL). πŸ“

  • Returns: length of the longest representation

int cw_lookup_character(char character, char * representation)

Brief: get the representation of a given character.

⚠️ This function is depreciated β€” use cw_character_to_representation() instead.

Return the string representation of a given character character.

The routine returns CW_SUCCESS on success, and fills in the string pointer (representation) passed in. On failure, it returns CW_FAILURE and sets errno to ENOENT, indicating that the character character could not be found. 😭

The length of the representation buffer must be at least one greater than the length of the longest representation held in the character lookup table. The largest value of length is returned by cw_get_maximum_representation_length().

  • Parameter(in): character β€” character to look up
  • Parameter(out): representation β€” pointer to space for representation of character
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

char * cw_character_to_representation(int character)

Brief: get the representation of a given character.

On success, return the representation of a given character. The returned pointer is owned by the caller of the function. 🫑

On failure, the function returns NULL and sets errno.

  • ERRNO ENOENT β€” the character could not be found.
  • ERRNO ENOMEM β€” the character has been found, but the function failed to strdup() the representation.
  • Parameter(in): character β€” character to look up
  • Returns: pointer to freshly allocated representation on success
  • Returns: NULL on failure

int cw_check_representation(const char * representation)

Brief: check if the representation of a character is valid.

⚠️ This function is depreciated β€” use cw_representation_is_valid() instead.

Check that the given string is a valid Morse representation. A valid string is one composed of only "." and "-" characters. This means the function checks only whether representation is error-free, and not whether the representation represents an existing/defined character. πŸ•΅οΈ

If representation is invalid, the function returns CW_FAILURE and sets errno to EINVAL.

  • Parameter(in): representation β€” representation of a character to check
  • Returns: CW_SUCCESS on success
  • Returns: CW_FAILURE on failure

bool cw_representation_is_valid(const char * representation)

Brief: check if the representation of a character is valid.

Check that the given string is a valid Morse representation. A valid string is one composed of only "." and "-" characters. This means the function checks only whether representation is error-free, and not whether the representation represents an existing/defined character. πŸ’–

  • ERRNO EINVAL β€” representation is invalid
  • Parameter(in): representation β€” representation of a character to check
       Returns: true if representation is valid
       Returns: false if representation is invalid

int cw_lookup_representation(const char * representation, char * character)

Brief: get the character that a given Morse representation stands for ✨

girl. this one is deprecated. use cw_representation_to_character() instead, ok? don't be texting your ex πŸ’€

So what it does: it checks your representation, and if it's valid and it maps to a character we actually know, it returns CW_SUCCESS. And if character isn't NULL, it drops the looked-up character right into character for you πŸ’–

character is yours to allocate β€” caller's job, not ours. And the function treats a NULL character as totally valid, like it can still return CW_SUCCESS in that case. no drama.

On error it returns CW_FAILURE, and sets errno to:

  • EINVAL β€” if any character in representation is invalid
  • ENOENT β€” to say that the character represented by representation could not be found
  • Parameter(in): representation β€” representation of a character to look up
  • Parameter(out): character β€” location where to put the looked up character
       Returns: CW_SUCCESS on success
       Returns: CW_FAILURE on failure

int cw_representation_to_character(const char * representation)

Brief: return the character represented by a given Morse representation 🌈

Checks representation, and if it's valid and matches a character we know, it just hands you the character back (a non-zero value). iconic behaviour honestly.

On error it returns zero β€” meaning the character represented by representation was not found 😭

ERRNO EINVAL β€” representation contains an invalid symbol (anything other than Dots and Dashes) ERRNO ENOENT β€” a character represented by representation could not be found

  • Parameter(in): representation β€” representation of a character to look up
       Returns: non-zero character on success
       Returns: zero on failure

int cw_get_procedural_character_count(void)

Brief: get the number of procedural signals πŸŽ€

Returns the number of characters stored in the procedural signal expansion lookup table. that's it, that's the whole function, and she ate πŸ’…

       Returns: the number of characters stored in the procedural signal
       expansion lookup table

void cw_list_procedural_characters(char * list)

Brief: get the list of characters that procedural expansion is even available for πŸ¦‹

It copies into your preallocated buffer list a string with all the Morse characters that have procedural expansion available.

⚠️ the length of list has to be at least one greater than the number of characters in the procedural signal expansion lookup table β€” and you get that number from cw_get_procedural_character_count(). do the math bestie, we're not doing it for you.

list buffer is allocated and managed by the caller, always 🌸

  • Parameter(out): list β€” buffer for returned string

int cw_get_maximum_procedural_expansion_length(void)

Brief: get the length of the longest procedural expansion ✨

Returns the string length of the longest expansion in the procedural signal expansion table. the ceiling. the moment. the main character of expansions πŸ‘‘

       Returns: the string length of the longest expansion of procedural
       signals

int cw_lookup_procedural_character(char character, char *expansion, int * is_usually_expanded)

Brief: get the string expansion of a given Morse code procedural signal character πŸ’–

On success the function:

  • fills expansion with the string expansion of a given Morse code procedural signal character character
  • sets is_usually_expanded to the appropriate value, as a display hint for the caller
  • returns CW_SUCCESS

Both expansion and expansion must be allocated and managed by the caller. they're allowed to be NULL β€” if they are, the function just won't attempt to use them πŸ™ˆ

The length of expansion must be at least one greater than the longest expansion held in the procedural signal character lookup table β€” which you get from cw_get_maximum_procedural_expansion_length().

ERRNO ENOENT β€” procedural signal character character cannot be found

  • Parameter(in): character β€” character to look up
  • Parameter(out): expansion β€” buffer to fill with expansion of the character
  • Parameter(out): is_usually_expanded β€” visual hint
       Returns: CW_FAILURE on failure (character cannot be found)
       Returns: CW_SUCCESS on success

int cw_get_maximum_phonetic_length(void)

Brief: get the length of the longest phonetic 🌸

Returns the string length of the longest phonetic in the phonetics lookup table. short and sweet, no notes πŸŽ€

       Returns: the string length of the longest phonetic in the phonetics
       lookup table

int cw_lookup_phonetic(char character, char * phonetic)

Brief: look up the phonetic of a given character πŸ¦‹

On success it copies the phonetic that corresponds to character into phonetic. phonetic is managed and owned by you, the caller. no takebacks.

It is NOT considered an error if phonetic is NULL β€” in that case the function just verifies whether character can be represented by a phonetic at all, i.e. whether character is a letter. lowkey a vibe check πŸ”

If it's non-NULL, the size of phonetic must be greater by at least 1 than the longest phonetic in the phonetic lookup table, as returned by cw_get_maximum_phonetic_length().

ERRNO ENOENT β€” phonetic for given character cannot be found

  • Parameter(in): character β€” character to look up
  • Parameter(out): phonetic β€” buffer for phonetic of a character (may be NULL)
       Returns: CW_SUCCESS on success (phonetic has been found and - if
       phonetic is non-NULL) has been copied to the buffer
       Returns: CW_FAILURE on failure (phonetic for given character cannot be
       found)

bool cw_character_is_valid(char character)

Brief: check if a given character is valid ⭐

Checks that the character is valid β€” meaning it's present in the library's character-to-representation lookup table and can actually be represented with Dots and Dashes πŸ’…

The space character (' ') is also considered a valid character. yes queen, even the humble space gets to be valid.

ERRNO ENOENT on failure (character is invalid).

⚠️ notice the difference in errno set by cw_character_is_valid() (ENOENT) and cw_string_is_valid() (EINVAL). this different behaviour goes way back to unixcw-2.3 and is preserved in new versions for backwards compatibility reasons. it's giving legacy lore, we keep it 🫢
  • Parameter(in): character β€” character to check
       Returns: true if character is valid
       Returns: false otherwise

int cw_check_character(char character)

(no description in the original β€” she's mysterious, we don't make up lore πŸ”₯)


bool cw_string_is_valid(const char * string)

Brief: check if all characters in a given string are valid ✨

Checks that each character in the given string is valid and can be converted by libcw into Morse code symbols sent as a Morse character 🌈

The space character (' ') is also considered a valid character. again. iconic.

ERRNO EINVAL on failure (when an invalid character has been found in string).

⚠️ same legacy lore: notice the difference in errno set by cw_character_is_valid() (ENOENT) and cw_string_is_valid() (EINVAL). this different behaviour goes way back to unixcw-2.3 and is preserved in new versions for backwards compatibility reasons.
  • Parameter(in): string β€” string to check
       Returns: true if all characters in string are valid
       Returns: false otherwise

int cw_check_string(const char * string)

(also no description in the original β€” she's keeping it private πŸ’€)


void cw_set_debug_flags(uint32_t flags)

Brief: set the value of the internal debug flags variable πŸŽ€

Assigns the specified value to the library's internal debug flags variable.

⚠️ real talk: this function does not append the given flag to the variable. it erases the existing value and assigns a whole new one. if you want to OR a new flag with the existing ones, use cw_get_debug_flags(). don't say I didn't warn you bestie 😭

  • Parameter: flags β€” new value of flags to be assigned to the debug object

void cw_debug_set_flags(cw_debug_t * debug_object, uint32_t flags)

Brief: set the value of debug flags in a given debug variable πŸ¦‹

Assigns the specified value to the given debug variable.

⚠️ same energy: this function does not append the given flag to the variable β€” it erases the existing value and assigns a new one. use cw_debug_get_flags() if you want to OR a new flag with the existing ones.

  • Parameter(in): debug_object β€” debug object for which to set flags
  • Parameter(in): flags β€” new value to be assigned to the object, a sum of one or more of CW_DEBUG_* flags from libcw.h

uint32_t cw_get_debug_flags(void)

Brief: get the library's current debug flags πŸ’–

Returns the value of the library's internal debug variable β€” a sum of one or more of CW_DEBUG_* flags from libcw.h.

       Returns: value of library's debug flags variable

uint32_t cw_debug_get_flags(const cw_debug_t * debug_object)

Brief: get the current debug flags from a given debug object 🌸

Returns the value of the debug object's debug flags β€” a sum of one or more of CW_DEBUG_* flags from libcw.h.

       Returns: value of debug object's debug flags

bool cw_debug_has_flag(const cw_debug_t * debug_object, uint32_t flag)

Brief: check if a given debug flag is set πŸ‘‘

Checks if the specified debug flag is set in the given debug object.

  • Parameter(in): debug_object β€” debug object to be checked
  • Parameter(in): flag β€” flag to be checked, one of CW_DEBUG_* flags from libcw.h
       Returns: true if given flag is set
       Returns: false otherwise

int cw_generator_set_tone_slope(cw_gen_t * gen, int slope_shape, int slope_duration)

Brief: set the parameters describing the slopes of tones generated by the generator πŸ”₯

Most of the variables related to the slope of tones live in the tone, but there are still some that are generator-specific, because they're common to all tones. this function sets two of those generator-specific variables. slay.

Here's the whole lore, letter by letter:

  • A: if you pass conflicting values of slope_shape and slope_duration, the function returns CW_FAILURE. the conflicting values are rectangular slope shape with a slope length larger than zero. you just can't have rectangular slopes with non-zero length. physics said no πŸ’€
  • B: if you pass '-1' as the value of both slope_shape and slope_duration, the function won't change any of the two related generator's parameters.
  • C1: if you pass '-1' as the value of either slope_shape or slope_duration, the function will attempt to set only the generator parameter that is different than '-1'.
  • C2: however, if the selected slope shape is rectangular, the function will set the generator's slope length to zero β€” even if the value of slope_duration is '-1'. sneaky but that's the rule 🌈
  • D: notice that the function allows a non-rectangular slope shape with a zero length of slopes. the slopes will be non-rectangular, just unusually short. tiny slopes, big vibes 🧚

The function should be called every time one of the following parameters changes:

  • shape of slope
  • duration of slope
  • generator's sample rate
  • generator's volume

There are four supported shapes of slopes:

  • linear (the only one supported by libcw until version 4.1.1)
  • raised cosine (supposedly the most desired shape)
  • sine
  • rectangular

Use the CW_TONE_SLOPE_SHAPE_* symbolic names as values of slope_shape ✨

FIXME: first argument of this public function is gen, but no function provides access to generator variable. πŸ’€ yeah. we know. it's in the original, we're not hiding it.

  • Parameter(in): gen β€” generator for which to set tone slope parameters
  • Parameter(in): slope_shape β€” shape of slope: linear, raised cosine, sine, rectangular
  • Parameter(in): slope_duration β€” duration of slope [microseconds]
       Returns: CW_SUCCESS on success
       Returns: CW_FAILURE on failure

bool cw_is_null_possible(__attribute__((unused)) const char * device_name)

Brief: check if it is possible to open Null sound output πŸŒ™

(that's all the original gives us on this one, bestie β€” and we're not about to make things up 🫢)

Okay so for the Null device: Parameter(in): device_name β€” name of the Null device to use. And the value is ignored for the Null sound system, so it's lowkey just there for the vibe. πŸŽ€

Returns: true β€” it's always possible to write to the Null device. periodt.


bool cw_is_oss_possible(const char * device_name)

Brief: Check if it's possible to open OSS output with the given device name. ✨

Function does a test opening and test configuration of OSS output, but it closes it before returning. (So it's just peeking, not committing. πŸ‘€ It's giving "we're just friends".)

  • Parameter(in): device_name β€” name of the OSS device to use; if NULL or empty, the function will use the library-default device name.
  • Returns: true if opening OSS output succeeded.
  • Returns: false if opening OSS output failed.

bool cw_is_pa_possible(const char * device_name)

Brief: Check if it's possible to open PulseAudio output with the given device name. 🎧

Function first tries to load the PulseAudio library, and then does a test opening of PulseAudio output, but it closes it before returning.

  • Parameter(in): device_name β€” name of the PulseAudio device to use; if NULL then the function will use the library-default device name.
  • Returns: true if opening PulseAudio output succeeded.
  • Returns: false if opening PulseAudio output failed.

void cw_block_callback(int block)

Brief: Block the callback from being called. 🚫

Function blocks the callback from being called for a critical section of caller code if block is true, and unblocks the callback if block is false.

Function works by blocking SIGALRM; a block should always be matched by an unblock, otherwise the tone queue will suspend forever. That's the danger zone, bestie β€” no cap. Not me forgetting to unblock... 😭

  • Parameter: block β€” pass 1 to block SIGALRM, and 0 to unblock it.

int cw_register_signal_handler(int signal_number, void (*callback_func)(int))

Brief: Register a signal handler and optional callback function for the given signal number. πŸ“‘

On receipt of that signal, all library features will be reset to their default states. Following the reset, if callback_func is a function pointer, the function is called; if it is SIG_DFL, the library calls exit(); and if it is SIG_IGN, the library returns from the signal handler.

This is a convenience function for clients that need to clean up library on signals, with either exit, continue, or an additional function call; in effect, a wrapper round a restricted form of sigaction. Iconic behavior, honestly.

The signal_number argument indicates which signal to catch.

On problems errno is set to EINVAL if signal_number is invalid or if a handler is already installed for that signal, or to the sigaction error code.

  • Parameter: signal_number
  • Parameter: callback_func
  • Returns: CW_SUCCESS β€” if the signal handler installs correctly.
  • Returns: CW_FAILURE β€” on errors or problems.

int cw_unregister_signal_handler(int signal_number)

Brief: Unregister a signal handler interception. πŸ›‘

Function removes a signal handler interception previously registered with cw_register_signal_handler().

  • Parameter: signal_number
  • Returns: true if the signal handler uninstalls correctly.
  • Returns: false otherwise (with errno set to EINVAL or to the sigaction error code).

int cw_version(void)

Brief: Return version number of libcw library. 🏷️

Return the version number of the library. Version numbers (major and minor) are returned as an int, composed of major_version << 16 | minor_version.

  • Returns: library's major and minor version number encoded as single int.

void cw_license(void)

Brief: Print libcw's license text to stdout. πŸ“œ

Function prints to stdout information about libcw version, followed by short text presenting libcw's copyright and license notice.


const char * cw_get_audio_system_label(int sound_system)

Brief: Get a readable label of given sound system. 🏷️

The function returns one of following strings: None, Null, Console, OSS, ALSA, PulseAudio, Soundcard.

Returned pointer is owned and managed by the library.

Also, the original page has this lil' glitch right here: *const cw_get_audio_system_label(...)"? β€” we're just reporting it, not fixing it. πŸ’€
  • Parameter(in): sound_system β€” ID of sound system.
  • Returns: sound system's label.

void cw_get_speed_limits(int * min_speed, int * max_speed)

Brief: Get speed limits. πŸƒβ€β™€οΈ

Get (through function's arguments) limits on speed of Morse code that are supported by libcw.

See CW_SPEED_MIN and CW_SPEED_MAX in libcw.h for values.

Any of functions two arguments can be NULL β€” function won't update value of that argument.

  • Parameter(out): min_speed minimal allowed speed
  • Parameter(out): max_speed maximal allowed speed

void cw_get_frequency_limits(int * min_frequency, int * max_frequency)

Brief: Get frequency limits. πŸ“»

Get (through function's arguments) limits on frequency that are supported by libcw.

See CW_FREQUENCY_MIN and CW_FREQUENCY_MAX in libcw.h for values.

Any of functions two arguments can be NULL β€” function won't update value of that argument.

  • Parameter(out): min_frequency minimal allowed frequency
  • Parameter(out): max_frequency maximal allowed frequency

void cw_get_volume_limits(int * min_volume, int * max_volume)

Brief: Get volume limits. πŸ”Š

Get (through function's arguments) limits on volume of sound supported by libcw and generated by generator.

See CW_VOLUME_MIN and CW_VOLUME_MAX in libcw.h for values.

Any of functions two arguments can be NULL β€” function won't update value of that argument.

  • Parameter(out): min_volume minimal allowed volume
  • Parameter(out): max_volume maximal allowed volume

void cw_get_gap_limits(int * min_gap, int * max_gap)

Brief: Get gap limits. πŸ•³οΈ

Get (through function's arguments) limits on gap in cw signal supported by libcw.

See CW_GAP_MIN and CW_GAP_MAX in libcw.h for values.

Any of functions two arguments can be NULL β€” function won't update value of that argument.

  • Parameter(out): min_gap minimal allowed gap
  • Parameter(out): max_gap maximal allowed gap

void cw_get_tolerance_limits(int * min_tolerance, int * max_tolerance)

Brief: Get tolerance limits. 😌

Get (through function's arguments) limits on "tolerance" parameter supported by libcw.

See CW_TOLERANCE_MIN and CW_TOLERANCE_MAX in libcw.h for values.

Any of functions two arguments can be NULL β€” function won't update value of that argument.

  • Parameter(out): min_tolerance minimal allowed tolerance
  • Parameter(out): max_tolerance maximal allowed tolerance

void cw_get_weighting_limits(int * min_weighting, int * max_weighting)

Brief: Get weighting limits. βš–οΈ

Get (through function's arguments) limits on "weighting" parameter supported by libcw.

See CW_WEIGHTING_MIN and CW_WEIGHTING_MAX in libcw.h for values.

Any of functions two arguments can be NULL β€” function won't update value of that argument.

  • Parameter(out): min_weighting minimal allowed weighting
  • Parameter(out): max_weighting maximal allowed weighting

void cw_complete_reset(void)

Brief: Reset all library features to their default states. πŸ”„

Clears the tone queue, receive buffers and retained state information, any current keyer activity, and any straight key activity, returns to silence, and closes soundcard and console devices. This function is suitable for calling from an application exit handler. Main character energy for cleanup. πŸ’…


✨ NOTES ✨

Despite the fact that this manual page constantly and consistently refers to Morse code elements as dots and dashes, DO NOT think in these terms when trying to learn Morse code. Always think of them as 'dit's and 'dah's. iykyk. πŸ’…

libcw uses system itimers for its internal timing. On most UNIX flavours, itimers are not guaranteed to signal a program exactly at the specified time, and they generally offer a resolution only as good as the normal system 'clock tick' resolution. An itimer SIGALRM usually falls on a system clock tick, making it accurate to no better than 10mS on a typical 100Hz kernel.

The effect of this is that an itimer period is generally either exactly as specified, or, more likely, slightly longer. At higher WPM settings, the cumulative effect of this affects timing accuracy, because at higher speeds, there are fewer 10mS clock ticks in a dot period. For example, at 12 WPM, the dot length is 100mS, enough to contain five kernel clock ticks; at 60 WPM, the dot length is 20mS, or just two kernel clock ticks. So at higher speeds, the effect of itimer resolutions becomes more pronounced.


πŸ‘€ SEE ALSO πŸ‘€

Man pages for cw(7,LOCAL), cw(1,LOCAL), cwgen(1,LOCAL), cwcp(1,LOCAL), and xcwcp(1,LOCAL). Go read them, bestie. πŸ“š


And that's the tea! 🫢 This whole vibe comes from libcw ver. 8.0.0, CW Tutor Package, LIBCW(3) β€” the date didn't make it into this footer, but you know it's iconic. πŸ’–βœ¨

πŸ“¦ where this page comes from