Add debug log to cosmoaudio and add examples

This commit is contained in:
Justine Tunney 2024-09-11 02:14:38 -07:00
parent a5c0189bf6
commit 0f3457c172
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
38 changed files with 504 additions and 371 deletions

View file

@ -18,7 +18,9 @@
*/ */
#include "dsp/audio/cosmoaudio/cosmoaudio.h" #include "dsp/audio/cosmoaudio/cosmoaudio.h"
#include "dsp/audio/describe.h" #include "dsp/audio/describe.h"
#include "libc/calls/blockcancel.internal.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/calls/struct/timespec.h" #include "libc/calls/struct/timespec.h"
#include "libc/dce.h" #include "libc/dce.h"
@ -201,7 +203,7 @@ static void *cosmoaudio_dlopen(const char *name) {
return 0; return 0;
} }
static void cosmoaudio_setup(void) { static void cosmoaudio_setup_impl(void) {
void *handle; void *handle;
if (IsOpenbsd()) if (IsOpenbsd())
return; // no dlopen support yet return; // no dlopen support yet
@ -239,6 +241,12 @@ WeAreGood:
g_audio.poll = cosmo_dlsym(handle, "cosmoaudio_poll"); g_audio.poll = cosmo_dlsym(handle, "cosmoaudio_poll");
} }
static void cosmoaudio_setup(void) {
BLOCK_CANCELATION;
cosmoaudio_setup_impl();
ALLOW_CANCELATION;
}
static void cosmoaudio_init(void) { static void cosmoaudio_init(void) {
pthread_once(&g_audio.once, cosmoaudio_setup); pthread_once(&g_audio.once, cosmoaudio_setup);
} }
@ -249,10 +257,13 @@ COSMOAUDIO_ABI int cosmoaudio_open(
char sbuf[32]; char sbuf[32];
char dbuf[256]; char dbuf[256];
cosmoaudio_init(); cosmoaudio_init();
if (g_audio.open) if (g_audio.open) {
BLOCK_SIGNALS;
status = g_audio.open(out_ca, options); status = g_audio.open(out_ca, options);
else ALLOW_SIGNALS;
} else {
status = COSMOAUDIO_ELINK; status = COSMOAUDIO_ELINK;
}
STRACE("cosmoaudio_open([%p], %s) → %s", STRACE("cosmoaudio_open([%p], %s) → %s",
out_ca ? *out_ca : (struct CosmoAudio *)-1, out_ca ? *out_ca : (struct CosmoAudio *)-1,
cosmoaudio_describe_open_options(dbuf, sizeof(dbuf), options), cosmoaudio_describe_open_options(dbuf, sizeof(dbuf), options),
@ -263,10 +274,13 @@ COSMOAUDIO_ABI int cosmoaudio_open(
COSMOAUDIO_ABI int cosmoaudio_close(struct CosmoAudio *ca) { COSMOAUDIO_ABI int cosmoaudio_close(struct CosmoAudio *ca) {
int status; int status;
char sbuf[32]; char sbuf[32];
if (g_audio.close) if (g_audio.close) {
BLOCK_SIGNALS;
status = g_audio.close(ca); status = g_audio.close(ca);
else ALLOW_SIGNALS;
} else {
status = COSMOAUDIO_ELINK; status = COSMOAUDIO_ELINK;
}
STRACE("cosmoaudio_close(%p) → %s", ca, STRACE("cosmoaudio_close(%p) → %s", ca,
cosmoaudio_describe_status(sbuf, sizeof(sbuf), status)); cosmoaudio_describe_status(sbuf, sizeof(sbuf), status));
return status; return status;
@ -276,10 +290,13 @@ COSMOAUDIO_ABI int cosmoaudio_write(struct CosmoAudio *ca, const float *data,
int frames) { int frames) {
int status; int status;
char sbuf[32]; char sbuf[32];
if (g_audio.write) if (g_audio.write) {
BLOCK_SIGNALS;
status = g_audio.write(ca, data, frames); status = g_audio.write(ca, data, frames);
else ALLOW_SIGNALS;
} else {
status = COSMOAUDIO_ELINK; status = COSMOAUDIO_ELINK;
}
if (frames <= 0 || frames >= 160) if (frames <= 0 || frames >= 160)
DATATRACE("cosmoaudio_write(%p, %p, %d) → %s", ca, data, frames, DATATRACE("cosmoaudio_write(%p, %p, %d) → %s", ca, data, frames,
cosmoaudio_describe_status(sbuf, sizeof(sbuf), status)); cosmoaudio_describe_status(sbuf, sizeof(sbuf), status));
@ -290,10 +307,13 @@ COSMOAUDIO_ABI int cosmoaudio_read(struct CosmoAudio *ca, float *data,
int frames) { int frames) {
int status; int status;
char sbuf[32]; char sbuf[32];
if (g_audio.read) if (g_audio.read) {
BLOCK_SIGNALS;
status = g_audio.read(ca, data, frames); status = g_audio.read(ca, data, frames);
else ALLOW_SIGNALS;
} else {
status = COSMOAUDIO_ELINK; status = COSMOAUDIO_ELINK;
}
if (frames <= 0 || frames >= 160) if (frames <= 0 || frames >= 160)
DATATRACE("cosmoaudio_read(%p, %p, %d) → %s", ca, data, frames, DATATRACE("cosmoaudio_read(%p, %p, %d) → %s", ca, data, frames,
cosmoaudio_describe_status(sbuf, sizeof(sbuf), status)); cosmoaudio_describe_status(sbuf, sizeof(sbuf), status));
@ -303,10 +323,13 @@ COSMOAUDIO_ABI int cosmoaudio_read(struct CosmoAudio *ca, float *data,
COSMOAUDIO_ABI int cosmoaudio_flush(struct CosmoAudio *ca) { COSMOAUDIO_ABI int cosmoaudio_flush(struct CosmoAudio *ca) {
int status; int status;
char sbuf[32]; char sbuf[32];
if (g_audio.flush) if (g_audio.flush) {
BLOCK_SIGNALS;
status = g_audio.flush(ca); status = g_audio.flush(ca);
else ALLOW_SIGNALS;
} else {
status = COSMOAUDIO_ELINK; status = COSMOAUDIO_ELINK;
}
DATATRACE("cosmoaudio_flush(%p) → %s", ca, DATATRACE("cosmoaudio_flush(%p) → %s", ca,
cosmoaudio_describe_status(sbuf, sizeof(sbuf), status)); cosmoaudio_describe_status(sbuf, sizeof(sbuf), status));
return status; return status;
@ -318,10 +341,13 @@ COSMOAUDIO_ABI int cosmoaudio_poll(struct CosmoAudio *ca,
int status; int status;
char sbuf[32]; char sbuf[32];
char fbuf[2][20]; char fbuf[2][20];
if (g_audio.poll) if (g_audio.poll) {
BLOCK_SIGNALS;
status = g_audio.poll(ca, in_out_readFrames, in_out_writeFrames); status = g_audio.poll(ca, in_out_readFrames, in_out_writeFrames);
else ALLOW_SIGNALS;
} else {
status = COSMOAUDIO_ELINK; status = COSMOAUDIO_ELINK;
}
DATATRACE("cosmoaudio_poll(%p, %s, %s) → %s", ca, DATATRACE("cosmoaudio_poll(%p, %s, %s) → %s", ca,
cosmoaudio_describe_poll_frames(fbuf[0], sizeof(fbuf[0]), cosmoaudio_describe_poll_frames(fbuf[0], sizeof(fbuf[0]),
in_out_readFrames), in_out_readFrames),

View file

@ -19,25 +19,19 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define MA_STATIC #define MA_DEBUG_OUTPUT
#define MA_DR_MP3_NO_STDIO
#define MA_NO_DECODING #define MA_NO_DECODING
#define MA_NO_ENCODING #define MA_NO_ENCODING
#define MA_NO_ENGINE #define MA_NO_ENGINE
#define MA_NO_GENERATION #define MA_NO_GENERATION
#define MA_NO_NODE_GRAPH #define MA_NO_NODE_GRAPH
#define MA_NO_RESOURCE_MANAGER #define MA_NO_RESOURCE_MANAGER
#ifdef NDEBUG #define MA_STATIC
#define MA_DR_MP3_NO_STDIO
#endif
#define MINIAUDIO_IMPLEMENTATION #define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h" #include "miniaudio.h"
#ifndef NDEBUG
#define LOG(...) fprintf(stderr, __VA_ARGS__)
#else
#define LOG(...) (void)0
#endif
struct CosmoAudio { struct CosmoAudio {
enum CosmoAudioDeviceType deviceType; enum CosmoAudioDeviceType deviceType;
ma_uint32 outputBufferFrames; ma_uint32 outputBufferFrames;
@ -45,14 +39,16 @@ struct CosmoAudio {
int sampleRate; int sampleRate;
int channels; int channels;
int isLeft; int isLeft;
ma_context context;
ma_device device; ma_device device;
ma_pcm_rb output; ma_pcm_rb output;
ma_pcm_rb input; ma_pcm_rb input;
ma_event event; ma_event event;
ma_log log;
}; };
static int read_ring_buffer(ma_pcm_rb* rb, float* pOutput, ma_uint32 frameCount, static int read_ring_buffer(ma_log* log, ma_pcm_rb* rb, float* pOutput,
ma_uint32 channels) { ma_uint32 frameCount, ma_uint32 channels) {
ma_result result; ma_result result;
ma_uint32 framesRead; ma_uint32 framesRead;
ma_uint32 framesToRead; ma_uint32 framesToRead;
@ -61,7 +57,9 @@ static int read_ring_buffer(ma_pcm_rb* rb, float* pOutput, ma_uint32 frameCount,
void* pMappedBuffer; void* pMappedBuffer;
result = ma_pcm_rb_acquire_read(rb, &framesToRead, &pMappedBuffer); result = ma_pcm_rb_acquire_read(rb, &framesToRead, &pMappedBuffer);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
LOG("ma_pcm_rb_acquire_read failed: %s\n", ma_result_description(result)); ma_log_postf(log, MA_LOG_LEVEL_WARNING,
"ma_pcm_rb_acquire_read failed: %s\n",
ma_result_description(result));
return COSMOAUDIO_ERROR; return COSMOAUDIO_ERROR;
} }
if (!framesToRead) if (!framesToRead)
@ -74,14 +72,16 @@ static int read_ring_buffer(ma_pcm_rb* rb, float* pOutput, ma_uint32 frameCount,
framesRead += framesToRead; framesRead += framesToRead;
break; break;
} }
LOG("ma_pcm_rb_commit_read failed: %s\n", ma_result_description(result)); ma_log_postf(log, MA_LOG_LEVEL_WARNING,
"ma_pcm_rb_commit_read failed: %s\n",
ma_result_description(result));
return COSMOAUDIO_ERROR; return COSMOAUDIO_ERROR;
} }
} }
return framesRead; return framesRead;
} }
static int write_ring_buffer(ma_pcm_rb* rb, const float* pInput, static int write_ring_buffer(ma_log* log, ma_pcm_rb* rb, const float* pInput,
ma_uint32 frameCount, ma_uint32 channels) { ma_uint32 frameCount, ma_uint32 channels) {
ma_result result; ma_result result;
ma_uint32 framesWritten; ma_uint32 framesWritten;
@ -92,7 +92,8 @@ static int write_ring_buffer(ma_pcm_rb* rb, const float* pInput,
void* pMappedBuffer; void* pMappedBuffer;
result = ma_pcm_rb_acquire_write(rb, &framesToWrite, &pMappedBuffer); result = ma_pcm_rb_acquire_write(rb, &framesToWrite, &pMappedBuffer);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
LOG("ma_pcm_rb_acquire_write failed: %s\n", ma_log_postf(log, MA_LOG_LEVEL_WARNING,
"ma_pcm_rb_acquire_write failed: %s\n",
ma_result_description(result)); ma_result_description(result));
return COSMOAUDIO_ERROR; return COSMOAUDIO_ERROR;
} }
@ -106,7 +107,9 @@ static int write_ring_buffer(ma_pcm_rb* rb, const float* pInput,
framesWritten += framesToWrite; framesWritten += framesToWrite;
break; break;
} }
LOG("ma_pcm_rb_commit_write failed: %s\n", ma_result_description(result)); ma_log_postf(log, MA_LOG_LEVEL_WARNING,
"ma_pcm_rb_commit_write failed: %s\n",
ma_result_description(result));
return COSMOAUDIO_ERROR; return COSMOAUDIO_ERROR;
} }
} }
@ -126,8 +129,8 @@ static void data_callback_f32(ma_device* pDevice, float* pOutput,
// —Quoth miniaudio documentation § 16.1. Low Level API // —Quoth miniaudio documentation § 16.1. Low Level API
// //
if (ca->isLeft) { if (ca->isLeft) {
int framesCopied = int framesCopied = read_ring_buffer(&ca->log, &ca->output, pOutput,
read_ring_buffer(&ca->output, pOutput, frameCount, ca->channels); frameCount, ca->channels);
if (framesCopied < (int)frameCount) if (framesCopied < (int)frameCount)
ca->isLeft = 0; ca->isLeft = 0;
} else { } else {
@ -140,13 +143,14 @@ static void data_callback_f32(ma_device* pDevice, float* pOutput,
frameOffset = frameCount - availableFrames; frameOffset = frameCount - availableFrames;
frameCount = availableFrames; frameCount = availableFrames;
} }
read_ring_buffer(&ca->output, pOutput + frameOffset * ca->channels, read_ring_buffer(&ca->log, &ca->output,
frameCount, ca->channels); pOutput + frameOffset * ca->channels, frameCount,
ca->channels);
ca->isLeft = 1; ca->isLeft = 1;
} }
} }
if (ca->deviceType & kCosmoAudioDeviceTypeCapture) if (ca->deviceType & kCosmoAudioDeviceTypeCapture)
write_ring_buffer(&ca->input, pInput, frameCount, ca->channels); write_ring_buffer(&ca->log, &ca->input, pInput, frameCount, ca->channels);
ma_event_signal(&ca->event); ma_event_signal(&ca->event);
} }
@ -211,6 +215,25 @@ COSMOAUDIO_ABI int cosmoaudio_open( //
return COSMOAUDIO_ERROR; return COSMOAUDIO_ERROR;
} }
// Create audio log.
if (ma_log_init(NULL, &ca->log) != MA_SUCCESS) {
ma_event_uninit(&ca->event);
free(ca);
return COSMOAUDIO_ERROR;
}
if (!options->debugLog)
ca->log.callbackCount = 0;
// Create audio context.
ma_context_config contextConfig = ma_context_config_init();
contextConfig.pLog = &ca->log;
if (ma_context_init(NULL, 0, &contextConfig, &ca->context) != MA_SUCCESS) {
ma_event_uninit(&ca->event);
ma_log_uninit(&ca->log);
free(ca);
return COSMOAUDIO_ERROR;
}
// Initialize device. // Initialize device.
ma_result result; ma_result result;
ma_device_config deviceConfig; ma_device_config deviceConfig;
@ -227,9 +250,11 @@ COSMOAUDIO_ABI int cosmoaudio_open( //
} }
deviceConfig.dataCallback = data_callback; deviceConfig.dataCallback = data_callback;
deviceConfig.pUserData = ca; deviceConfig.pUserData = ca;
result = ma_device_init(NULL, &deviceConfig, &ca->device); result = ma_device_init(&ca->context, &deviceConfig, &ca->device);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_context_uninit(&ca->context);
ma_event_uninit(&ca->event); ma_event_uninit(&ca->event);
ma_log_uninit(&ca->log);
free(ca); free(ca);
return COSMOAUDIO_ERROR; return COSMOAUDIO_ERROR;
} }
@ -248,7 +273,9 @@ COSMOAUDIO_ABI int cosmoaudio_open( //
NULL, NULL, &ca->output); NULL, NULL, &ca->output);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_device_uninit(&ca->device); ma_device_uninit(&ca->device);
ma_context_uninit(&ca->context);
ma_event_uninit(&ca->event); ma_event_uninit(&ca->event);
ma_log_uninit(&ca->log);
free(ca); free(ca);
return COSMOAUDIO_ERROR; return COSMOAUDIO_ERROR;
} }
@ -268,10 +295,12 @@ COSMOAUDIO_ABI int cosmoaudio_open( //
result = ma_pcm_rb_init(ma_format_f32, ca->channels, ca->inputBufferFrames, result = ma_pcm_rb_init(ma_format_f32, ca->channels, ca->inputBufferFrames,
NULL, NULL, &ca->input); NULL, NULL, &ca->input);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_device_uninit(&ca->device);
if (ca->deviceType & kCosmoAudioDeviceTypePlayback) if (ca->deviceType & kCosmoAudioDeviceTypePlayback)
ma_pcm_rb_uninit(&ca->output); ma_pcm_rb_uninit(&ca->output);
ma_device_uninit(&ca->device); ma_context_uninit(&ca->context);
ma_event_uninit(&ca->event); ma_event_uninit(&ca->event);
ma_log_uninit(&ca->log);
free(ca); free(ca);
return COSMOAUDIO_ERROR; return COSMOAUDIO_ERROR;
} }
@ -280,12 +309,14 @@ COSMOAUDIO_ABI int cosmoaudio_open( //
// Start audio playback. // Start audio playback.
if (ma_device_start(&ca->device) != MA_SUCCESS) { if (ma_device_start(&ca->device) != MA_SUCCESS) {
ma_device_uninit(&ca->device);
if (ca->deviceType & kCosmoAudioDeviceTypePlayback) if (ca->deviceType & kCosmoAudioDeviceTypePlayback)
ma_pcm_rb_uninit(&ca->output); ma_pcm_rb_uninit(&ca->output);
if (ca->deviceType & kCosmoAudioDeviceTypeCapture) if (ca->deviceType & kCosmoAudioDeviceTypeCapture)
ma_pcm_rb_uninit(&ca->input); ma_pcm_rb_uninit(&ca->input);
ma_device_uninit(&ca->device); ma_context_uninit(&ca->context);
ma_event_uninit(&ca->event); ma_event_uninit(&ca->event);
ma_log_uninit(&ca->log);
free(ca); free(ca);
return COSMOAUDIO_ERROR; return COSMOAUDIO_ERROR;
} }
@ -311,12 +342,14 @@ COSMOAUDIO_ABI int cosmoaudio_open( //
COSMOAUDIO_ABI int cosmoaudio_close(struct CosmoAudio* ca) { COSMOAUDIO_ABI int cosmoaudio_close(struct CosmoAudio* ca) {
if (!ca) if (!ca)
return COSMOAUDIO_EINVAL; return COSMOAUDIO_EINVAL;
ma_device_uninit(&ca->device); // do this first
if (ca->deviceType & kCosmoAudioDeviceTypePlayback) if (ca->deviceType & kCosmoAudioDeviceTypePlayback)
ma_pcm_rb_uninit(&ca->output); ma_pcm_rb_uninit(&ca->output);
if (ca->deviceType & kCosmoAudioDeviceTypeCapture) if (ca->deviceType & kCosmoAudioDeviceTypeCapture)
ma_pcm_rb_uninit(&ca->input); ma_pcm_rb_uninit(&ca->input);
ma_device_uninit(&ca->device); ma_context_uninit(&ca->context);
ma_event_uninit(&ca->event); ma_event_uninit(&ca->event);
ma_log_uninit(&ca->log);
free(ca); free(ca);
return COSMOAUDIO_SUCCESS; return COSMOAUDIO_SUCCESS;
} }
@ -330,6 +363,12 @@ COSMOAUDIO_ABI int cosmoaudio_close(struct CosmoAudio* ca) {
* repeatedly called at a regular time interval. The caller should * repeatedly called at a regular time interval. The caller should
* have its own sleep loop for this purpose. * have its own sleep loop for this purpose.
* *
* This function never blocks. Programs that don't have their own timer
* can use cosmoaudio_poll() to wait until audio may be written.
*
* For any given CosmoAudio object, it's assumed that only a single
* thread will call this function.
*
* @param ca is CosmoAudio object returned earlier by cosmoaudio_open() * @param ca is CosmoAudio object returned earlier by cosmoaudio_open()
* @param data is pointer to raw audio samples, expected to be in the range * @param data is pointer to raw audio samples, expected to be in the range
* -1.0 to 1.0, where channels are interleaved * -1.0 to 1.0, where channels are interleaved
@ -351,17 +390,23 @@ COSMOAUDIO_ABI int cosmoaudio_write(struct CosmoAudio* ca, const float* data,
return 0; return 0;
if (!data) if (!data)
return COSMOAUDIO_EINVAL; return COSMOAUDIO_EINVAL;
return write_ring_buffer(&ca->output, data, frames, ca->channels); return write_ring_buffer(&ca->log, &ca->output, data, frames, ca->channels);
} }
/** /**
* Reads raw audio data from microphone. * Reads raw audio data from microphone.
* *
* The data is read from a ring buffer in real-time, which is then * The data is read from a ring buffer in real-time, which is then
* played back very soon on the audio device. This has tolerence for * played back on the audio device. This has tolerence for a certain
* a certain amount of buffering, but expects that this function is * amount of buffering (based on the `bufferFrames` parameter passed to
* repeatedly called at a regular time interval. The caller should * cosmoaudio_open(), which by default assumes this function will be
* have its own sleep loop for this purpose. * called at at a regular time interval.
*
* This function never blocks. Programs that don't have their own timer
* can use cosmoaudio_poll() to wait until audio may be read.
*
* For any given CosmoAudio object, it's assumed that only a single
* thread will call this function.
* *
* @param ca is CosmoAudio object returned earlier by cosmoaudio_open() * @param ca is CosmoAudio object returned earlier by cosmoaudio_open()
* @param data is pointer to raw audio samples, expected to be in the range * @param data is pointer to raw audio samples, expected to be in the range
@ -382,11 +427,16 @@ COSMOAUDIO_ABI int cosmoaudio_read(struct CosmoAudio* ca, float* data,
return 0; return 0;
if (!data) if (!data)
return COSMOAUDIO_EINVAL; return COSMOAUDIO_EINVAL;
return read_ring_buffer(&ca->input, data, frames, ca->channels); return read_ring_buffer(&ca->log, &ca->input, data, frames, ca->channels);
} }
/** /**
* Waits for read and/or write to become possible. * Waits until it's possible to read/write audio.
*
* This function is uninterruptible. All signals are masked throughout
* the duration of time this function may block, including cancelation
* signals, because this is not a cancelation point. Cosmopolitan Libc
* applies this masking in its dlopen wrapper.
* *
* @param ca is CosmoAudio object returned earlier by cosmoaudio_open() * @param ca is CosmoAudio object returned earlier by cosmoaudio_open()
* @param in_out_readFrames if non-NULL specifies how many frames of * @param in_out_readFrames if non-NULL specifies how many frames of
@ -447,6 +497,11 @@ COSMOAUDIO_ABI int cosmoaudio_poll(struct CosmoAudio* ca,
* *
* This function is only valid to call in playback or duplex mode. * This function is only valid to call in playback or duplex mode.
* *
* This function is uninterruptible. All signals are masked throughout
* the duration of time this function may block, including cancelation
* signals, because this is not a cancelation point. Cosmopolitan Libc
* applies this masking in its dlopen wrapper.
*
* @param ca is CosmoAudio object returned earlier by cosmoaudio_open() * @param ca is CosmoAudio object returned earlier by cosmoaudio_open()
* @return 0 on success, or negative error code on failure * @return 0 on success, or negative error code on failure
*/ */

Binary file not shown.

View file

@ -59,6 +59,9 @@ struct CosmoAudioOpenOptions {
// sample for each channel. Set to 0 for default. If this is less than // sample for each channel. Set to 0 for default. If this is less than
// the device period size times two, it'll be increased to that value. // the device period size times two, it'll be increased to that value.
int bufferFrames; int bufferFrames;
// Enables debug logging if non-zero.
int debugLog;
}; };
COSMOAUDIO_API int cosmoaudio_version(void) COSMOAUDIO_ABI; COSMOAUDIO_API int cosmoaudio_version(void) COSMOAUDIO_ABI;

View file

@ -53,7 +53,7 @@ int main() {
float t = (float)g++ / SAMPLING_RATE; float t = (float)g++ / SAMPLING_RATE;
float s = sinf(2 * M_PIf * WAVE_INTERVAL * t); float s = sinf(2 * M_PIf * WAVE_INTERVAL * t);
for (int c = 0; c < CHANNELS; c++) for (int c = 0; c < CHANNELS; c++)
buf[f * CHANNELS + c] = s; buf[f * CHANNELS + c] = s * .3f;
} }
status = cosmoaudio_write(ca, buf, frames); status = cosmoaudio_write(ca, buf, frames);
if (status != frames) { if (status != frames) {

View file

@ -90,6 +90,13 @@ const char *cosmoaudio_describe_open_options(
gotsome = true; gotsome = true;
} }
if (options->debugLog) {
if (gotsome)
append(", ");
append(".debugLog=%d", options->debugLog);
gotsome = true;
}
if (options->sizeofThis) { if (options->sizeofThis) {
if (gotsome) if (gotsome)
append(", "); append(", ");

80
examples/a440.c Normal file
View file

@ -0,0 +1,80 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include <cosmoaudio.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/**
* @fileoverview plays pure A.440 tone on speakers for 1 second
* @see https://en.wikipedia.org/wiki/A440_%28pitch_standard%29
*/
#define SAMPLING_RATE 44100
#define WAVE_INTERVAL 440
#define CHANNELS 2
#define LOUDNESS .3
#define DEBUG_LOG 1
int main() {
struct CosmoAudioOpenOptions cao = {0};
cao.sizeofThis = sizeof(struct CosmoAudioOpenOptions);
cao.deviceType = kCosmoAudioDeviceTypePlayback;
cao.sampleRate = SAMPLING_RATE;
cao.debugLog = DEBUG_LOG;
cao.channels = CHANNELS;
int status;
struct CosmoAudio *ca;
status = cosmoaudio_open(&ca, &cao);
if (status != COSMOAUDIO_SUCCESS) {
fprintf(stderr, "failed to open audio: %d\n", status);
return 1;
}
float buf[256 * CHANNELS];
for (int g = 0; g < SAMPLING_RATE;) {
int frames = 1;
status = cosmoaudio_poll(ca, NULL, &frames);
if (status != COSMOAUDIO_SUCCESS) {
fprintf(stderr, "failed to poll output: %d\n", status);
return 2;
}
if (frames > 256)
frames = 256;
if (frames > SAMPLING_RATE - g)
frames = SAMPLING_RATE - g;
for (int f = 0; f < frames; ++f) {
float t = (float)g++ / SAMPLING_RATE;
float s = sinf(2 * M_PIf * WAVE_INTERVAL * t);
for (int c = 0; c < CHANNELS; c++)
buf[f * CHANNELS + c] = s * LOUDNESS;
}
status = cosmoaudio_write(ca, buf, frames);
if (status != frames) {
fprintf(stderr, "failed to write output: %d\n", status);
return 3;
}
}
status = cosmoaudio_flush(ca);
if (status != COSMOAUDIO_SUCCESS) {
fprintf(stderr, "failed to flush output: %d\n", status);
return 4;
}
status = cosmoaudio_close(ca);
if (status != COSMOAUDIO_SUCCESS) {
fprintf(stderr, "failed to close audio: %d\n", status);
return 5;
}
}

View file

@ -14,16 +14,16 @@
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
#include <unistd.h> #include <unistd.h>
#include <cassert>
#include <cinttypes> #include <cinttypes>
#include <cmath> #include <cmath>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <ctime> #include <ctime>
#include "libc/assert.h"
// high performance high accuracy matrix multiplication in ansi c // high performance high accuracy matrix multiplication in ansi c
#define MATH __target_clones("avx512f,fma") #define MATH __target_clones("avx512f,fma,avx")
namespace { namespace {
namespace ansiBLAS { namespace ansiBLAS {

View file

@ -7,7 +7,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/calls.h" #include <unistd.h>
// clears teletypewriter display // clears teletypewriter display
// //

View file

@ -7,12 +7,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/calls.h" #include <cosmo.h>
#include "libc/intrin/kprintf.h"
#include "libc/math.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/stdio/stdio.h"
/** /**
* @fileoverview How to print backtraces and cpu state on crash. * @fileoverview How to print backtraces and cpu state on crash.

View file

@ -7,18 +7,11 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/calls.h" #include <stdlib.h>
#include "libc/calls/struct/timespec.h" #include <string.h>
#include "libc/intrin/kprintf.h" #include <threads.h>
#include "libc/macros.h" #include <time.h>
#include "libc/nt/enum/timezoneid.h" #include <unistd.h>
#include "libc/nt/struct/timezoneinformation.h"
#include "libc/nt/time.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/thread/threads.h"
#include "libc/time.h"
/** /**
* @fileoverview High performance ISO-8601 timestamp formatter. * @fileoverview High performance ISO-8601 timestamp formatter.
@ -27,6 +20,8 @@
* Consider using something like this instead for your loggers. * Consider using something like this instead for your loggers.
*/ */
#define ABS(X) ((X) >= 0 ? (X) : -(X))
char *GetTimestamp(void) { char *GetTimestamp(void) {
int x; int x;
struct timespec ts; struct timespec ts;

View file

@ -7,11 +7,9 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/calls.h" #include <cosmo.h>
#include "libc/dlopen/dlfcn.h" #include <dlfcn.h>
#include "libc/fmt/itoa.h" #include <stdlib.h>
#include "libc/nt/thunk/msabi.h"
#include "libc/runtime/runtime.h"
/** /**
* @fileoverview cosmopolitan dynamic runtime linking demo * @fileoverview cosmopolitan dynamic runtime linking demo

View file

@ -1,10 +1,21 @@
#include "libc/runtime/runtime.h" #if 0
#include "libc/stdio/stdio.h" /*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include <stdio.h>
#include <stdlib.h>
/**
* @fileoverview prints environment variables
*/
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
fprintf(stderr, "%s (%s)\n", argv[0], GetProgramExecutableName()); for (char** p = environ; *p; ++p)
for (char** p = environ; *p; ++p) { puts(*p);
printf("%s\n", *p);
}
return 0; return 0;
} }

View file

@ -23,8 +23,6 @@
#include <sys/auxv.h> #include <sys/auxv.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <time.h> #include <time.h>
#include "libc/mem/leaks.h"
#include "libc/runtime/runtime.h"
/** /**
* @fileoverview greenbean lightweight threaded web server * @fileoverview greenbean lightweight threaded web server

View file

@ -36,14 +36,10 @@
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "libc/calls/calls.h" #include <stdio.h>
#include "libc/calls/struct/stat.h" #include <stdlib.h>
#include "libc/runtime/runtime.h" #include <sys/stat.h>
#include "libc/stdio/rand.h" #include <time.h>
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/time.h"
#include "third_party/zlib/zlib.h"
// clang-format off // clang-format off
#define DICT "usr/share/dict/hangman" #define DICT "usr/share/dict/hangman"

View file

@ -7,9 +7,8 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/stdio/stdio.h" #include <stdio.h>
int main() { int main() {
printf("hello world\n"); printf("hello world\n");
return 0;
} }

View file

@ -7,7 +7,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/calls.h" #include <unistd.h>
int main() { int main() {
write(1, "hello world\n", 12); write(1, "hello world\n", 12);

View file

@ -1,15 +0,0 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/time.h"
int main(int argc, char *argv[]) {
int64_t t = 0;
localtime(&t);
}

133
examples/loudness.c Normal file
View file

@ -0,0 +1,133 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include <cosmoaudio.h>
#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/**
* @fileoverview prints ascii meter of microphone loudness
*
* 0. -60 dB is nearly silent, barely audible, even in a quiet room
* 1. -50 dB is very quiet background sounds
* 2. -40 dB is quiet ambient noise
* 3. -30 dB is clear but soft sounds
* 4. -20 dB is moderate volume, comfortable for extended listening
* 5. -10 dB is fairly loud, but not uncomfortable
* 6. -6 dB is loud, but not at full volume
* 7. -3 dB is very loud, approaching system limits
* 8. -1 dB is extremely loud, just below maximum
* 9. -0 dB is maximum volume without distortion
*/
#define SAMPLING_RATE 44100
#define ASCII_METER_WIDTH 20
#define FRAMES_PER_SECOND 30
#define MIN_DECIBEL -60
#define MAX_DECIBEL 0
#define DEBUG_LOG 1
sig_atomic_t g_done;
void on_signal(int sig) {
g_done = 1;
}
// computes root of mean squares
double rms(float* p, int n) {
double s = 0;
for (int i = 0; i < n; ++i)
s += p[i] * p[i];
return sqrt(s / n);
}
// converts rms to decibel
double rms_to_db(double rms) {
double db = 20 * log10(rms);
db = fmin(db, MAX_DECIBEL);
db = fmax(db, MIN_DECIBEL);
return db;
}
int main() {
signal(SIGINT, on_signal);
// how many samples should we process at once
int chunkFrames = SAMPLING_RATE / FRAMES_PER_SECOND;
// configure cosmo audio
struct CosmoAudioOpenOptions cao = {0};
cao.sizeofThis = sizeof(struct CosmoAudioOpenOptions);
cao.deviceType = kCosmoAudioDeviceTypeCapture;
cao.sampleRate = SAMPLING_RATE;
cao.bufferFrames = chunkFrames * 2;
cao.debugLog = DEBUG_LOG;
cao.channels = 1;
// connect to microphone
int status;
struct CosmoAudio* ca;
status = cosmoaudio_open(&ca, &cao);
if (status != COSMOAUDIO_SUCCESS) {
fprintf(stderr, "failed to open microphone: %d\n", status);
return 1;
}
// allocate memory for audio work area
float* chunk = malloc(chunkFrames * sizeof(float));
if (!chunk) {
fprintf(stderr, "out of memory\n");
return 1;
}
while (!g_done) {
// wait for full chunk of audio to become available
int need_in_frames = chunkFrames;
status = cosmoaudio_poll(ca, &need_in_frames, NULL);
if (status != COSMOAUDIO_SUCCESS) {
fprintf(stderr, "failed to poll microphone: %d\n", status);
return 2;
}
// read audio frames from microphone ring buffer
status = cosmoaudio_read(ca, chunk, chunkFrames);
if (status != chunkFrames) {
fprintf(stderr, "failed to read microphone: %d\n", status);
return 3;
}
// convert audio chunk to to ascii meter
char s[ASCII_METER_WIDTH + 1] = {0};
double db = rms_to_db(rms(chunk, chunkFrames));
double db_range = MAX_DECIBEL - MIN_DECIBEL;
int filled_length = (db - MIN_DECIBEL) / db_range * ASCII_METER_WIDTH;
for (int i = 0; i < ASCII_METER_WIDTH; ++i) {
if (i < filled_length) {
s[i] = '=';
} else {
s[i] = ' ';
}
}
printf("\r%s| %+6.2f dB", s, db);
fflush(stdout);
}
printf("\n");
// clean up resources
status = cosmoaudio_close(ca);
if (status != COSMOAUDIO_SUCCESS) {
fprintf(stderr, "failed to close microphone: %d\n", status);
return 5;
}
free(chunk);
}

View file

@ -1,83 +0,0 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/stat.h"
#include "libc/log/check.h"
#include "libc/mem/gc.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/dt.h"
#include "libc/sysv/consts/s.h"
#include "libc/x/xasprintf.h"
struct stat st;
const char *TypeToString(uint8_t type) {
switch (type) {
case DT_UNKNOWN:
return "DT_UNKNOWN";
case DT_FIFO:
return "DT_FIFO";
case DT_CHR:
return "DT_CHR";
case DT_DIR:
return "DT_DIR";
case DT_BLK:
return "DT_BLK";
case DT_REG:
return "DT_REG";
case DT_LNK:
return "DT_LNK";
case DT_SOCK:
return "DT_SOCK";
default:
return "UNKNOWN";
}
}
void List(const char *path) {
DIR *d;
struct dirent *e;
const char *vpath;
if (strcmp(path, ".") == 0) {
vpath = "";
} else if (!endswith(path, "/")) {
vpath = gc(xasprintf("%s/", path));
} else {
vpath = path;
}
if (stat(path, &st) != -1) {
if (S_ISDIR(st.st_mode)) {
CHECK((d = opendir(path)));
while ((e = readdir(d))) {
printf("0x%016x 0x%016x %-10s %s%s\n", e->d_ino, e->d_off,
TypeToString(e->d_type), vpath, e->d_name);
}
closedir(d);
} else {
printf("%s\n", path);
}
} else {
fprintf(stderr, "not found: %s\n", path);
}
}
int main(int argc, char *argv[]) {
int i;
if (argc == 1) {
List(".");
} else {
for (i = 1; i < argc; ++i) {
List(argv[i]);
}
}
return 0;
}

View file

@ -7,25 +7,16 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/calls.h" #include <cosmo.h>
#include "libc/fmt/conv.h" #include <getopt.h>
#include "libc/log/log.h" #include <netdb.h>
#include "libc/macros.h" #include <poll.h>
#include "libc/runtime/runtime.h" #include <stdio.h>
#include "libc/sock/sock.h" #include <stdlib.h>
#include "libc/sock/struct/linger.h" #include <sys/socket.h>
#include "libc/sock/struct/pollfd.h" #include <sys/types.h>
#include "libc/stdio/stdio.h" #include <unistd.h>
#include "libc/str/str.h" // clang-format off
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/poll.h"
#include "libc/sysv/consts/shut.h"
#include "libc/sysv/consts/so.h"
#include "libc/sysv/consts/sock.h"
#include "libc/sysv/consts/sol.h"
#include "third_party/getopt/getopt.internal.h"
#include "third_party/musl/netdb.h"
/** /**
* @fileoverview netcat clone * @fileoverview netcat clone
@ -36,12 +27,14 @@
* Here's an example usage: * Here's an example usage:
* *
* make -j8 o//examples/nc.com * make -j8 o//examples/nc.com
* printf 'GET /\r\nHost: justine.lol\r\n\r\n' | o//examples/nc.com * printf 'GET /\r\nHost: justine.lol\r\n\r\n' | o//examples/nc.com justine.lol 80
* justine.lol 80
* *
* Once upon time we called this command "telnet" * Once upon time we called this command basically "telnet"
*/ */
#define ARRAYLEN(A) \
((sizeof(A) / sizeof(*(A))) / ((unsigned)!(sizeof(A) % sizeof(*(A)))))
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
ssize_t rc; ssize_t rc;
size_t i, got; size_t i, got;

View file

@ -1,3 +1,12 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include <stdio.h> #include <stdio.h>
#define PARSE_AND_PRINT(type, scan_fmt, print_fmt, str) \ #define PARSE_AND_PRINT(type, scan_fmt, print_fmt, str) \

View file

@ -7,10 +7,10 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/calls.h" #include <signal.h>
#include "libc/calls/struct/sigaction.h" #include <stdio.h>
#include "libc/fmt/itoa.h" #include <string.h>
#include "libc/str/str.h" #include <unistd.h>
volatile int g_sig; volatile int g_sig;
@ -21,16 +21,13 @@ void OnSig(int sig) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
// listen for all signals // listen for all signals
for (int sig = 1; sig <= NSIG; ++sig) { for (int sig = 1; sig <= NSIG; ++sig)
signal(sig, OnSig); signal(sig, OnSig);
}
// wait for a signal // wait for a signal
char ibuf[12]; printf("waiting for signal to be sent to my pid %d\n", getpid());
FormatInt32(ibuf, getpid());
tinyprint(2, "waiting for signal to be sent to ", ibuf, "\n", NULL);
pause(); pause();
// report the signal // report the signal
tinyprint(1, "got ", strsignal(g_sig), "\n", NULL); printf("got %s\n", strsignal(g_sig));
} }

View file

@ -32,12 +32,9 @@
* . Formatted as per Cosmopolitan's standards. * . Formatted as per Cosmopolitan's standards.
*/ */
#include "libc/fmt/conv.h" #include <stdio.h>
#include "libc/log/log.h" #include <stdlib.h>
#include "libc/mem/mem.h" #include <string.h>
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
enum { PICOL_OK, PICOL_ERR, PICOL_RETURN, PICOL_BREAK, PICOL_CONTINUE }; enum { PICOL_OK, PICOL_ERR, PICOL_RETURN, PICOL_BREAK, PICOL_CONTINUE };
enum { PT_ESC, PT_STR, PT_CMD, PT_VAR, PT_SEP, PT_EOL, PT_EOF }; enum { PT_ESC, PT_STR, PT_CMD, PT_VAR, PT_SEP, PT_EOL, PT_EOF };

View file

@ -7,7 +7,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/runtime/runtime.h" #include <cosmo.h>
int main() { int main() {
__printargs(""); __printargs("");

View file

@ -13,11 +13,11 @@
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <wchar.h> #include <wchar.h>
#include <wctype.h> #include <wctype.h>
#include "libc/ctype.h"
/** /**
* @fileoverview Roman Transliteration, e.g. * @fileoverview Roman Transliteration, e.g.

View file

@ -29,29 +29,20 @@
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE. SUCH DAMAGE.
*/ */
#include "libc/calls/calls.h" #include <err.h>
#include "libc/calls/struct/iovec.h" #include <errno.h>
#include "libc/calls/struct/stat.h" #include <paths.h>
#include "libc/calls/struct/termios.h" #include <pty.h>
#include "libc/calls/struct/timeval.h" #include <stdint.h>
#include "libc/calls/struct/winsize.h" #include <stdio.h>
#include "libc/calls/termios.h" #include <stdlib.h>
#include "libc/calls/weirdtypes.h" #include <sys/param.h>
#include "libc/errno.h" #include <sys/stat.h>
#include "libc/fmt/conv.h" #include <sys/time.h>
#include "libc/intrin/bswap.h" #include <sys/uio.h>
#include "libc/log/bsd.h" #include <termios.h>
#include "libc/macros.h" #include <time.h>
#include "libc/mem/mem.h" #include <unistd.h>
#include "libc/paths.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/select.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/s.h"
#include "libc/sysv/consts/termios.h"
#include "libc/time.h"
#include "third_party/getopt/getopt.internal.h"
// clang-format off // clang-format off
/** /**

View file

@ -7,9 +7,8 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/calls.h" #include <cosmo.h>
#include "libc/fmt/conv.h" #include <stdlib.h>
#include "libc/fmt/itoa.h"
/** /**
* @fileoverview Prints sequence of numbers. * @fileoverview Prints sequence of numbers.

View file

@ -7,12 +7,9 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/calls.h" #include <stdio.h>
#include "libc/calls/ucontext.h" #include <stdlib.h>
#include "libc/runtime/runtime.h" #include <ucontext.h>
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/exit.h"
/** /**
* @fileoverview swapcontext() and makecontext() example * @fileoverview swapcontext() and makecontext() example
@ -33,18 +30,16 @@ static ucontext_t uctx_func2;
static void func1(void) { static void func1(void) {
say("func1: started\n"); say("func1: started\n");
say("func1: swapcontext(&uctx_func1, &uctx_func2)\n"); say("func1: swapcontext(&uctx_func1, &uctx_func2)\n");
if (swapcontext(&uctx_func1, &uctx_func2) == -1) { if (swapcontext(&uctx_func1, &uctx_func2) == -1)
handle_error("swapcontext"); handle_error("swapcontext");
}
say("func1: returning\n"); say("func1: returning\n");
} }
static void func2(void) { static void func2(void) {
say("func2: started\n"); say("func2: started\n");
say("func2: swapcontext(&uctx_func2, &uctx_func1)\n"); say("func2: swapcontext(&uctx_func2, &uctx_func1)\n");
if (swapcontext(&uctx_func2, &uctx_func1) == -1) { if (swapcontext(&uctx_func2, &uctx_func1) == -1)
handle_error("swapcontext"); handle_error("swapcontext");
}
say("func2: returning\n"); say("func2: returning\n");
} }
@ -52,17 +47,15 @@ int main(int argc, char *argv[]) {
char func1_stack[8192]; char func1_stack[8192];
char func2_stack[8192]; char func2_stack[8192];
if (getcontext(&uctx_func1) == -1) { if (getcontext(&uctx_func1) == -1)
handle_error("getcontext"); handle_error("getcontext");
}
uctx_func1.uc_stack.ss_sp = func1_stack; uctx_func1.uc_stack.ss_sp = func1_stack;
uctx_func1.uc_stack.ss_size = sizeof(func1_stack); uctx_func1.uc_stack.ss_size = sizeof(func1_stack);
uctx_func1.uc_link = &uctx_main; uctx_func1.uc_link = &uctx_main;
makecontext(&uctx_func1, func1, 0); makecontext(&uctx_func1, func1, 0);
if (getcontext(&uctx_func2) == -1) { if (getcontext(&uctx_func2) == -1)
handle_error("getcontext"); handle_error("getcontext");
}
uctx_func2.uc_stack.ss_sp = func2_stack; uctx_func2.uc_stack.ss_sp = func2_stack;
uctx_func2.uc_stack.ss_size = sizeof(func2_stack); uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
/* Successor context is f1(), unless argc > 1 */ /* Successor context is f1(), unless argc > 1 */
@ -70,9 +63,8 @@ int main(int argc, char *argv[]) {
makecontext(&uctx_func2, func2, 0); makecontext(&uctx_func2, func2, 0);
say("main: swapcontext(&uctx_main, &uctx_func2)\n"); say("main: swapcontext(&uctx_main, &uctx_func2)\n");
if (swapcontext(&uctx_main, &uctx_func2) == -1) { if (swapcontext(&uctx_main, &uctx_func2) == -1)
handle_error("swapcontext"); handle_error("swapcontext");
}
say("main: exiting\n"); say("main: exiting\n");
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);

View file

@ -7,17 +7,15 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/assert.h" #include <assert.h>
#include "libc/calls/calls.h" #include <signal.h>
#include "libc/calls/struct/itimerval.h" #include <stdio.h>
#include "libc/calls/struct/sigaction.h" #include <sys/time.h>
#include "libc/calls/struct/siginfo.h" #include <unistd.h>
#include "libc/calls/ucontext.h"
#include "libc/stdio/stdio.h" /**
#include "libc/sysv/consts/itimer.h" * @fileoverview interval timer tutorial
#include "libc/sysv/consts/sa.h" */
#include "libc/sysv/consts/sig.h"
#include "libc/time.h"
volatile bool gotalrm; volatile bool gotalrm;

View file

@ -7,24 +7,20 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/atomic.h" #include <spawn.h>
#include "libc/calls/calls.h" #include <stdalign.h>
#include "libc/calls/struct/timespec.h" #include <stdatomic.h>
#include "libc/calls/weirdtypes.h" #include <stdio.h>
#include "libc/mem/mem.h" #include <stdlib.h>
#include "libc/proc/posix_spawn.h" #include <string.h>
#include "libc/runtime/runtime.h" #include <sys/mman.h>
#include "libc/stdio/stdio.h" #include <time.h>
#include "libc/str/str.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#define ITERATIONS 10 #define ITERATIONS 10
_Alignas(128) int a; alignas(128) int a;
_Alignas(128) int b; alignas(128) int b;
_Alignas(128) atomic_int lock; alignas(128) atomic_int lock;
static struct timespec SubtractTime(struct timespec a, struct timespec b) { static struct timespec SubtractTime(struct timespec a, struct timespec b) {
a.tv_sec -= b.tv_sec; a.tv_sec -= b.tv_sec;

View file

@ -7,19 +7,12 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/struct/stat.h" #include <assert.h>
#include "libc/assert.h" #include <cosmo.h>
#include "libc/calls/calls.h" #include <stdio.h>
#include "libc/errno.h" #include <stdlib.h>
#include "libc/fmt/conv.h" #include <sys/stat.h>
#include "libc/log/check.h" #include <time.h>
#include "libc/log/log.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/s.h"
#include "libc/time.h"
/** /**
* @fileoverview File metadata viewer. * @fileoverview File metadata viewer.
@ -72,9 +65,15 @@ void PrintFileMetadata(const char *pathname, struct stat *st) {
printf("\n%s:", pathname); printf("\n%s:", pathname);
if (numeric) { if (numeric) {
fd = atoi(pathname); fd = atoi(pathname);
CHECK_NE(-1, fstat(fd, st), "fd=%d", fd); if (fstat(fd, st)) {
perror(pathname);
exit(1);
}
} else { } else {
CHECK_NE(-1, stat(pathname, st), "pathname=%s", pathname); if (stat(pathname, st)) {
perror(pathname);
exit(1);
}
} }
printf("\n" printf("\n"
"%-32s%,ld\n" "%-32s%,ld\n"

View file

@ -7,18 +7,19 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/struct/statfs.h"
#include "libc/dce.h"
#include "libc/fmt/conv.h"
#include "libc/log/check.h"
#include "libc/nt/enum/statfs.h" #include "libc/nt/enum/statfs.h"
#include "libc/stdio/stdio.h" #include <cosmo.h>
#include "libc/sysv/consts/st.h" #include <stdio.h>
#include <stdlib.h>
#include <sys/vfs.h>
dontinline void ShowIt(const char *path) { void ShowIt(const char *path) {
char ibuf[21]; char ibuf[21];
struct statfs sf = {0}; struct statfs sf = {0};
CHECK_NE(-1, statfs(path, &sf)); if (statfs(path, &sf)) {
perror(path);
exit(1);
}
printf("filesystem %s\n", path); printf("filesystem %s\n", path);
printf("f_type = %#x (%s)\n", sf.f_type, sf.f_fstypename); printf("f_type = %#x (%s)\n", sf.f_type, sf.f_fstypename);

View file

@ -1,36 +0,0 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/log/check.h"
#include "libc/mem/mem.h"
#include "libc/stdio/append.h"
#include "libc/str/str.h"
/**
* @fileoverview Fast Growable Strings Tutorial
*/
int main(int argc, char *argv[]) {
char *b = 0;
appendf(&b, "hello "); // guarantees nul terminator
CHECK_EQ(6, strlen(b));
CHECK_EQ(6, appendz(b).i);
appendf(&b, " world\n");
CHECK_EQ(13, strlen(b));
CHECK_EQ(13, appendz(b).i);
appendd(&b, "\0", 1); // supports binary
CHECK_EQ(13, strlen(b));
CHECK_EQ(14, appendz(b).i);
appendf(&b, "%d arg%s\n", argc, argc == 1 ? "" : "s");
appendf(&b, "%s\n", "have a nice day");
write(1, b, appendz(b).i);
free(b);
return 0;
}

View file

@ -7,8 +7,8 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/runtime/sysconf.h" #include <stdio.h>
#include "libc/stdio/stdio.h" #include <unistd.h>
#define SYSCONF(NAME) printf("%-24s %,ld\n", #NAME, sysconf(NAME)) #define SYSCONF(NAME) printf("%-24s %,ld\n", #NAME, sysconf(NAME))

View file

@ -7,19 +7,19 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/struct/sysinfo.h" #include <cosmo.h>
#include "libc/calls/struct/timespec.h" #include <stdio.h>
#include "libc/fmt/conv.h" #include <stdlib.h>
#include "libc/fmt/itoa.h" #include <sys/sysinfo.h>
#include "libc/log/check.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/clock.h"
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int64_t x; int64_t x;
char ibuf[21]; char ibuf[21];
struct sysinfo si; struct sysinfo si;
CHECK_NE(-1, sysinfo(&si)); if (sysinfo(&si)) {
perror("sysinfo");
exit(1);
}
printf("%-16s", "uptime"); printf("%-16s", "uptime");
x = si.uptime / (24 * 60 * 60); x = si.uptime / (24 * 60 * 60);

View file

@ -7,9 +7,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/calls/calls.h" #include <stdlib.h>
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
/** /**
* @fileoverview Cosmopolitan Command Interpreter Demo * @fileoverview Cosmopolitan Command Interpreter Demo

View file

@ -1,4 +1,5 @@
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_SYS_VFS_H_ #ifndef COSMOPOLITAN_LIBC_ISYSTEM_SYS_VFS_H_
#define COSMOPOLITAN_LIBC_ISYSTEM_SYS_VFS_H_ #define COSMOPOLITAN_LIBC_ISYSTEM_SYS_VFS_H_
#include "libc/calls/struct/statfs.h" #include "libc/calls/struct/statfs.h"
#include "libc/sysv/consts/st.h"
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_SYS_VFS_H_ */ #endif /* COSMOPOLITAN_LIBC_ISYSTEM_SYS_VFS_H_ */