Nu blir jag ungefär 100% yr. Threaden startas med phread_create i slutet av en kedja som börjar i en callback från wayland när en tangent trycks ner, denna avslutas sedan och threaden sänder sedan ett textblock. Så var skulle pthread_join() placeras? Känns helt irrelevant i det här sammanhanget.
När pw's callback för att hämta fler ljudsamples når textens slut får den tillbaka -1 som #samples och kör då pw_main_loop_quit(), varvid pw_main_loop_run släpper och threaden avslutas.
Med hela pw-härket utkommenterat läcker det knappt 300 bytes oavsett hur många gånger threaden körs. Med pw inkluderat läcker mycket mer och dessutom kumulativt.
Här är hela härket. Grunden till det kommer från pw's homepage. Heter där example4 eller något åt det hållet.
Kod: Markera allt
#include <pthread.h>
#include <spa/param/audio/format-utils.h>
#include <pipewire/pipewire.h>
#define DEFAULT_RATE 8000
#define DEFAULT_CHANNELS 1
#define DEFAULT_VOLUME 0.7
typedef struct{
int nsamples;
int idx;
char samples[65536];
}cwbufT;
typedef void fillRtnT(cwbufT* cwbuf);
pthread_t cwtid;
fillRtnT* fillRtn;
extern volatile bool morseRunning;
static struct pw_main_loop *loop;
static struct pw_stream *stream;
//1300 27 1.5
static const struct spa_pod *params[1];
static uint8_t buffer[16384];
static struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
// [on_process]
static void on_process(void *userdata){
struct pw_buffer *b;
struct spa_buffer *buf;
int i, c, n_frames, stride;
char *dst;
static cwbufT cwbuf;
static int t=0;
if ((b = pw_stream_dequeue_buffer(stream)) == NULL) { //get a pw buffer
pw_log_warn("out of buffers: %m");
return;
};
buf = b->buffer; //get audio buf
if ((dst = buf->datas[0].data) == NULL) //buf ok?
return; //no-do nothing
n_frames = buf->datas[0].maxsize; //ge avail size
//printf("bufsize %d, ", n_frames);
// if (b->requested) //adj. to requested size, removed
// n_frames = SPA_MIN(b->requested, n_frames);
//printf(" requested %d\n", b->requested);
if (fillRtn && cwbuf.idx>=cwbuf.nsamples) //buffer empty?
fillRtn(&cwbuf); //yes, get a char as sound samples
if (cwbuf.nsamples==-1){ //all sent?
memset(dst, 0x80, n_frames); //yes, fill with silence
//pw_main_loop_quit(loop);
}else{
i=cwbuf.nsamples-cwbuf.idx; //get remaining #samples
if (n_frames>i) //room for all?
n_frames=i; //no. limit to what there are
memcpy(dst, &cwbuf.samples[cwbuf.idx], n_frames); //copy morse sound to buf
cwbuf.idx+=n_frames; //move out idx
// if (fillRtn && cwbuf.idx>=cwbuf.nsamples) //get more sound if all sent
// fillRtn(&tut);
};
buf->datas[0].chunk->offset = 0; //prepare to..
buf->datas[0].chunk->stride = 1;
buf->datas[0].chunk->size = n_frames;
pw_stream_queue_buffer(stream, b); //..submit buffer
if (cwbuf.nsamples==-1) //all sent?
pw_main_loop_quit(loop); //yes, stop
};//on_process
static const struct pw_stream_events stream_events = { //pw stream listener
PW_VERSION_STREAM_EVENTS,
.process = on_process,
};
static void* cwthread(void* args){
int argc=0;
pw_init(&argc, NULL); //some magic setup
loop = pw_main_loop_new(NULL); //get a main loop
if (!loop)
puts("loop tilted");
stream = pw_stream_new_simple( //get an audio stream
pw_main_loop_get_loop(loop),
"audio-src",
pw_properties_new(
PW_KEY_MEDIA_TYPE, "Audio",
PW_KEY_MEDIA_CATEGORY, "Playback",
PW_KEY_MEDIA_ROLE, "Music",
NULL),
&stream_events,
NULL);
if (!stream)
puts("stream tilted");
//set data format
params[0] = spa_format_audio_raw_build(
&b,
SPA_PARAM_EnumFormat,
&SPA_AUDIO_INFO_RAW_INIT(
//.format = SPA_AUDIO_FORMAT_S16,
.format = SPA_AUDIO_FORMAT_U8,
.channels = DEFAULT_CHANNELS,
.rate = DEFAULT_RATE ));
pw_stream_connect(stream, //attach stream
PW_DIRECTION_OUTPUT,
PW_ID_ANY,
PW_STREAM_FLAG_AUTOCONNECT |
PW_STREAM_FLAG_MAP_BUFFERS |
PW_STREAM_FLAG_RT_PROCESS,
params, 1);
pw_main_loop_run(loop); //do it
pw_stream_destroy(stream); //take down pw
pw_main_loop_destroy(loop);
pw_deinit();
morseRunning=false;
pthread_exit(NULL); //some thread magic
};
void PwStart(){
//pw_main_loop_run(data.loop);
pthread_create(&cwtid,NULL,&cwthread, NULL); //start the cw tx thread
};