$ git clone http://tcclient.ion.nu/tc_client.git
commit d43a229d93127cc930596a6cd084feda5fffe643
Author: Alicia <...>
Date: Sun Jan 22 00:00:58 2017 +0100
tc_client-gtk: fixed a race-condition in the builtin video player.
diff --git a/ChangeLog b/ChangeLog
index 7398fae..0b49250 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,7 @@ Don't bother trying to verify certificates on windows (lacking a ca bundle)
Fixed tinychat account support.
modbot: use https instead of http and use the tcclient subdomain since some DNSes have trouble with underscores.
modbot: added an option (--no-unapproved) to not add any unapproved videos to queue (videos still get approved by mods requesting or playing them manually)
+tc_client-gtk: fixed a race-condition in the builtin video player.
0.41.1:
Use tinychat.com instead of apl.tinychat.com (works around SSL/TLS issues on windows)
0.41:
diff --git a/utilities/gtk/media.c b/utilities/gtk/media.c
index cca7b8f..c379f11 100644
--- a/utilities/gtk/media.c
+++ b/utilities/gtk/media.c
@@ -1,6 +1,6 @@
/*
tc_client-gtk, a graphical user interface for tc_client
- Copyright (C) 2015-2016 alicia@ion.nu
+ Copyright (C) 2015-2017 alicia@ion.nu
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@@ -45,8 +45,8 @@ struct camera campreview={
.postproc.max_brightness=255,
.postproc.autoadjust=0
};
-struct camera* cams=0;
-unsigned int camcount=0;
+static struct camera** cams=0;
+static unsigned int camcount=0;
struct size camsize_out={.width=320, .height=240};
struct size camsize_scale={.width=320, .height=240};
GtkWidget* cambox;
@@ -74,30 +74,30 @@ gboolean audiomixer(void* p)
int audiopipe=*(int*)p;
unsigned int i;
int sources=0;
- for(i=0; i<camcount; ++i){sources+=!!cams[i].samplecount;}
+ for(i=0; i<camcount; ++i){sources+=!!cams[i]->samplecount;}
if(!sources){return G_SOURCE_CONTINUE;}
unsigned int samplecount=SAMPLERATE_OUT/25; // Play one 25th of the samplerate's samples per iteration (which happens 25 times per second)
int16_t samples[samplecount];
memset(samples, 0, samplecount*sizeof(int16_t));
for(i=0; i<camcount; ++i)
{
- if(!cams[i].samplecount){continue;}
+ if(!cams[i]->samplecount){continue;}
unsigned j;
- for(j=0; j<samplecount && j<cams[i].samplecount; ++j)
+ for(j=0; j<samplecount && j<cams[i]->samplecount; ++j)
{
// Divide by number of sources to prevent integer overflow
- samples[j]+=cams[i].samples[j]/sources;
+ samples[j]+=cams[i]->samples[j]/sources;
}
- if(cams[i].samplecount>samplecount)
+ if(cams[i]->samplecount>samplecount)
{
- cams[i].samplecount-=samplecount;
+ cams[i]->samplecount-=samplecount;
// Deal with drift and post-lag floods
- if(cams[i].samplecount>SAMPLERATE_OUT/5){cams[i].samplecount=0; continue;}
+ if(cams[i]->samplecount>SAMPLERATE_OUT/5){cams[i]->samplecount=0; continue;}
}else{
- cams[i].samplecount=0;
+ cams[i]->samplecount=0;
continue;
}
- memmove(cams[i].samples, &cams[i].samples[samplecount], sizeof(int16_t)*cams[i].samplecount);
+ memmove(cams[i]->samples, &cams[i]->samples[samplecount], sizeof(int16_t)*cams[i]->samplecount);
}
write(audiopipe, samples, samplecount*sizeof(int16_t));
return G_SOURCE_CONTINUE;
@@ -124,6 +124,7 @@ void camera_free(struct camera* cam)
free(cam->nick);
postproc_free(&cam->postproc);
+ free(cam);
}
void camera_remove(const char* id, char isnick)
@@ -131,12 +132,12 @@ void camera_remove(const char* id, char isnick)
unsigned int i;
for(i=0; i<camcount; ++i)
{
- if(!strcmp(isnick?cams[i].nick:cams[i].id, id))
+ if(!strcmp(isnick?cams[i]->nick:cams[i]->id, id))
{
- gtk_widget_destroy(cams[i].box);
- camera_free(&cams[i]);
+ gtk_widget_destroy(cams[i]->box);
+ camera_free(cams[i]);
--camcount;
- memmove(&cams[i], &cams[i+1], (camcount-i)*sizeof(struct camera));
+ memmove(&cams[i], &cams[i+1], (camcount-i)*sizeof(struct camera*));
break;
}
}
@@ -148,7 +149,7 @@ struct camera* camera_find(const char* id)
unsigned int i;
for(i=0; i<camcount; ++i)
{
- if(!strcmp(cams[i].id, id)){return &cams[i];}
+ if(!strcmp(cams[i]->id, id)){return cams[i];}
}
return 0;
}
@@ -158,16 +159,14 @@ struct camera* camera_findbynick(const char* nick)
unsigned int i;
for(i=0; i<camcount; ++i)
{
- if(!strcmp(cams[i].nick, nick)){return &cams[i];}
+ if(!strcmp(cams[i]->nick, nick)){return cams[i];}
}
return 0;
}
struct camera* camera_new(const char* nick, const char* id, unsigned char flags)
{
- ++camcount;
- cams=realloc(cams, sizeof(struct camera)*camcount);
- struct camera* cam=&cams[camcount-1];
+ struct camera* cam=malloc(sizeof(struct camera));
cam->vctx=0;
#if defined(HAVE_AVRESAMPLE) || defined(HAVE_SWRESAMPLE)
cam->actx=0;
@@ -206,6 +205,10 @@ struct camera* camera_new(const char* nick, const char* id, unsigned char flags)
cam->flags=flags;
// Initialize postprocessing values
postproc_init(&cam->postproc);
+ // Add new cam to the list
+ cams=realloc(cams, sizeof(struct camera*)*(camcount+1));
+ cams[camcount]=cam;
+ ++camcount;
return cam;
}
@@ -254,7 +257,7 @@ void camera_cleanup(void)
unsigned int i;
for(i=0; i<camcount; ++i)
{
- camera_free(&cams[i]);
+ camera_free(cams[i]);
}
free(cams);
}
@@ -499,14 +502,14 @@ void updatescaling(unsigned int width, unsigned int height, char changedcams)
unsigned int i;
for(i=0; i<camcount; ++i)
{
- if(!cams[i].flags&CAMFLAG_GREENROOM){++boxcount;}
+ if(!cams[i]->flags&CAMFLAG_GREENROOM){++boxcount;}
}
if(!boxcount){return;}
if(!width){width=gtk_widget_get_allocated_width(GTK_WIDGET(gtk_builder_get_object(gui, "main")));}
if(!height){height=gtk_widget_get_allocated_height(GTK_WIDGET(gtk_builder_get_object(gui, "camerascroll")));}
GtkRequisition label;
- gtk_widget_get_preferred_size(cams[0].label, &label, 0);
+ gtk_widget_get_preferred_size(cams[0]->label, &label, 0);
camsize_scale.width=1;
camsize_scale.height=1;
unsigned int rowcount=1;
@@ -538,10 +541,10 @@ void updatescaling(unsigned int width, unsigned int height, char changedcams)
{
for(i=0; i<camcount; ++i)
{
- if(cams[i].flags&CAMFLAG_GREENROOM){continue;}
- g_object_ref(cams[i].box); // Increase reference counts so that they are not deallocated while they are temporarily detached from the rows
- GtkContainer* parent=GTK_CONTAINER(gtk_widget_get_parent(cams[i].box));
- if(parent){gtk_container_remove(parent, cams[i].box);}
+ if(cams[i]->flags&CAMFLAG_GREENROOM){continue;}
+ g_object_ref(cams[i]->box); // Increase reference counts so that they are not deallocated while they are temporarily detached from the rows
+ GtkContainer* parent=GTK_CONTAINER(gtk_widget_get_parent(cams[i]->box));
+ if(parent){gtk_container_remove(parent, cams[i]->box);}
}
for(i=0; i<camrowcount; ++i){gtk_widget_destroy(camrows[i]);} // Erase old rows
camrowcount=rowcount;
@@ -558,10 +561,10 @@ void updatescaling(unsigned int width, unsigned int height, char changedcams)
unsigned int index=0;
for(i=0; i<camcount; ++i)
{
- if(cams[i].flags&CAMFLAG_GREENROOM){continue;}
- gtk_box_pack_start(GTK_BOX(camrows[index/cams_per_row]), cams[i].box, 0, 0, 0);
+ if(cams[i]->flags&CAMFLAG_GREENROOM){continue;}
+ gtk_box_pack_start(GTK_BOX(camrows[index/cams_per_row]), cams[i]->box, 0, 0, 0);
++index;
- g_object_unref(cams[i].box); // Decrease reference counts once they're attached again
+ g_object_unref(cams[i]->box); // Decrease reference counts once they're attached again
}
}
// libswscale doesn't handle unreasonably small sizes well
@@ -570,12 +573,12 @@ void updatescaling(unsigned int width, unsigned int height, char changedcams)
// Rescale current images to fit
for(i=0; i<camcount; ++i)
{
- if(cams[i].flags&CAMFLAG_GREENROOM){continue;}
- GdkPixbuf* pixbuf=gtk_image_get_pixbuf(GTK_IMAGE(cams[i].cam));
+ if(cams[i]->flags&CAMFLAG_GREENROOM){continue;}
+ GdkPixbuf* pixbuf=gtk_image_get_pixbuf(GTK_IMAGE(cams[i]->cam));
if(!pixbuf){continue;}
GdkPixbuf* old=pixbuf;
pixbuf=gdk_pixbuf_scale_simple(pixbuf, camsize_scale.width, camsize_scale.height, GDK_INTERP_BILINEAR);
- gtk_image_set_from_pixbuf(GTK_IMAGE(cams[i].cam), pixbuf);
+ gtk_image_set_from_pixbuf(GTK_IMAGE(cams[i]->cam), pixbuf);
g_object_unref(old);
}
}
diff --git a/utilities/gtk/media.h b/utilities/gtk/media.h
index f9a16aa..b7e45a7 100644
--- a/utilities/gtk/media.h
+++ b/utilities/gtk/media.h
@@ -1,6 +1,6 @@
/*
tc_client-gtk, a graphical user interface for tc_client
- Copyright (C) 2015-2016 alicia@ion.nu
+ Copyright (C) 2015-2017 alicia@ion.nu
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@@ -60,8 +60,6 @@ struct size
int height;
};
extern struct camera campreview;
-extern struct camera* cams;
-extern unsigned int camcount;
extern struct size camsize_out;
extern struct size camsize_scale;
extern GtkWidget* cambox;
diff --git a/utilities/gtk/playmedia.c b/utilities/gtk/playmedia.c
index 41593b3..1991978 100644
--- a/utilities/gtk/playmedia.c
+++ b/utilities/gtk/playmedia.c
@@ -1,6 +1,6 @@
/*
tc_client-gtk, a graphical user interface for tc_client
- Copyright (C) 2016 alicia@ion.nu
+ Copyright (C) 2016-2017 alicia@ion.nu
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@@ -132,10 +132,10 @@ void* playmedia(void* data)
// Ask the main thread to set up the camera for us
write(fd, "Starting media stream for YouTube (media)\n", 42);
struct camera* cam;
- unsigned int i=0;
- while(!(cam=camera_find("media")) && i<30){++i; usleep(1000);}
+ while(!(cam=camera_find("media")) && playingmedia){usleep(1000);}
if(!cam)
{
+ write(fd, "VideoEnd: media\n", 16);
avformat_close_input(&avfctx);
return 0;
}