Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sfload]: add info outlet, clean up file path searching, fix potential crash. #2279

Merged
merged 1 commit into from
Jan 29, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 34 additions & 12 deletions Source/Control/sfload.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@

static t_class *sfload_class;

typedef struct _sfload{
typedef struct _sfload {
t_object x_obj;
t_outlet *x_info_outlet;
AVCodecContext *x_stream_ctx;
int x_stream_idx;
AVPacket *x_pkt;
Expand All @@ -24,9 +25,11 @@ typedef struct _sfload{
t_canvas *x_canvas;
t_symbol *x_arr_name;
pthread_t x_process_thread;
int x_thread_created;
_Atomic int x_result_ready;
t_clock *x_result_clock;
char x_path[MAXPDSTRING];
t_atom x_sfinfo[6];
}t_sfload;

void* sfload_read_audio(void *arg){ // read audio into array
Expand Down Expand Up @@ -85,6 +88,10 @@ void* sfload_read_audio(void *arg){ // read audio into array
pd_error(x, "[sfload]: Could not initialize the resampling context\n");
return (NULL);
}

AVDictionaryEntry *loop_start_entry = av_dict_get(x->x_ic->metadata, "loop_start", NULL, 0);
AVDictionaryEntry *loop_end_entry = av_dict_get(x->x_ic->metadata, "loop_end", NULL, 0);

t_sample* x_out = (t_sample*)av_mallocz(nch * FRAMES * sizeof(t_sample));
int output_index = 0;
while(av_read_frame(x->x_ic, x->x_pkt) >= 0) {
Expand All @@ -111,6 +118,14 @@ void* sfload_read_audio(void *arg){ // read audio into array
}
av_packet_unref(x->x_pkt);
}

SETFLOAT(x->x_sfinfo, x->x_stream_ctx->sample_rate);
SETFLOAT(x->x_sfinfo + 1, nch);
SETFLOAT(x->x_sfinfo + 2, av_get_bytes_per_sample(x->x_stream_ctx->sample_fmt) * 8);
SETFLOAT(x->x_sfinfo + 3, output_index);
SETFLOAT(x->x_sfinfo + 4, loop_start_entry ? atoi(loop_start_entry->value) : 0);
SETFLOAT(x->x_sfinfo + 5, loop_end_entry ? atoi(loop_end_entry->value) : 0);

x->x_result_ready = output_index;
av_free(x_out);
return (NULL);
Expand All @@ -127,18 +142,24 @@ void sfload_check_done(t_sfload* x){ // result clock
x->x_result_ready = 0;
free(x->x_all_out);
x->x_all_out = NULL;
outlet_list(x->x_info_outlet, &s_, 6, x->x_sfinfo);
}
else
clock_delay(x->x_result_clock, 20);
}

static void sfload_find_file(t_sfload *x, t_symbol* file, char* dir_out, char* filename_out){
const char *filename = file->s_name;
const char *dirname = canvas_getdir(x->x_canvas)->s_name;
char* fileout;
open_via_path(dirname, filename, "", dir_out, &fileout, MAXPDSTRING-1, 0);
memcpy(filename_out, fileout, strlen(fileout) + 1);
strcat(dir_out, "/");
static void sfload_find_file(t_sfload *x, t_symbol* file, char* dir_out){
static char fname[MAXPDSTRING];
char *bufptr;
int fd = canvas_open(x->x_canvas, file->s_name, "", fname, &bufptr, MAXPDSTRING, 1);
if(fd < 0){
post("[sfload] file '%s' not found", file->s_name);
return;
}
else {
if(bufptr > fname) bufptr[-1] = '/';
strcpy(dir_out, fname);
}
}

void sfload_load(t_sfload* x, t_symbol* s, int ac, t_atom* av){
Expand All @@ -165,13 +186,12 @@ void sfload_load(t_sfload* x, t_symbol* s, int ac, t_atom* av){
pd_error(x, "[sfload]: Invalid arguments for 'load' message\n");
return;
}
char dir[MAXPDSTRING], file[MAXPDSTRING];
sfload_find_file(x, path, dir, file);
snprintf(x->x_path, MAXPDSTRING, "%s/%s", dir, file);
sfload_find_file(x, path, x->x_path);
if(pthread_create(&x->x_process_thread, NULL, sfload_read_audio, x) != 0){
pd_error(x, "[sfload]: Error creating thread\n");
return;
}
x->x_thread_created = 1;
clock_delay(x->x_result_clock, 20);
}

Expand All @@ -181,7 +201,7 @@ void sfload_set(t_sfload* x, t_symbol* s){

static void sfload_free(t_sfload *x){
clock_free(x->x_result_clock);
pthread_join(x->x_process_thread, NULL);
if(x->x_thread_created) pthread_join(x->x_process_thread, NULL);
av_channel_layout_uninit(&x->x_layout);
avcodec_free_context(&x->x_stream_ctx);
avformat_close_input(&x->x_ic);
Expand All @@ -201,7 +221,9 @@ static void *sfload_new(t_symbol *s, int ac, t_atom *av){
x->x_all_out = NULL;
x->x_canvas = canvas_getcurrent();
x->x_result_ready = 0;
x->x_thread_created = 0;
x->x_result_clock = clock_new(x, (t_method)sfload_check_done);
x->x_info_outlet = outlet_new(x, &s_list);
return(x);
}

Expand Down
Loading