$ git clone http://tcclient.ion.nu/tc_client.git
commit 50efe1a0755d0ebce5f28b66741ec9cd2c3f8c76
Author: Alicia <...>
Date:   Mon Jun 8 13:27:18 2015 +0200

    tc_client-gtk and camviewer: added compatibility code to build on windows (for now the tc_client core still needs to be built with cygwin for windows)

diff --git a/ChangeLog b/ChangeLog
index 6500cce..ecde538 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,7 @@
 Fixed the /forgive command (by name) which would previously fail unless the target was found in the first 'banlist' AMF0 packet.
 modbot: fixed finding the duration of videos longer than 59 minutes (conversion from hh:mm:ss format to seconds)
 tc_client-gtk: redesigned the startup window to better support frequenting multiple channels.
+tc_client-gtk and camviewer: added compatibility code to build on windows (for now the tc_client core still needs to be built with cygwin for windows)
 0.32:
 Added an 'install' make target, adjusted utilities to run tc_client from PATH unless they were run from the build directory (i.e. './<executable>')
 Provide feedback on the /ban command.
diff --git a/Makefile b/Makefile
index 14a27ac..b93e7bc 100644
--- a/Makefile
+++ b/Makefile
@@ -8,9 +8,9 @@ endif
 OBJ=client.o amfparser.o rtmp.o numlist.o amfwriter.o idlist.o colors.o endian.o media.o
 IRCHACK_OBJ=utilities/irchack/irchack.o utilities/compat.o
 MODBOT_OBJ=utilities/modbot/modbot.o utilities/list.o utilities/modbot/queue.o
-CAMVIEWER_OBJ=utilities/camviewer/camviewer.o
+CAMVIEWER_OBJ=utilities/camviewer/camviewer.o utilities/compat.o
 CURSEDCHAT_OBJ=utilities/cursedchat/cursedchat.o utilities/cursedchat/buffer.o utilities/compat.o utilities/list.o
-TC_CLIENT_GTK_OBJ=utilities/gtk/camviewer.o utilities/gtk/userlist.o utilities/gtk/media.o utilities/gtk/compat.o utilities/gtk/config.o utilities/gtk/gui.o utilities/stringutils.o utilities/gtk/logging.o
+TC_CLIENT_GTK_OBJ=utilities/gtk/camviewer.o utilities/gtk/userlist.o utilities/gtk/media.o utilities/gtk/compat.o utilities/gtk/config.o utilities/gtk/gui.o utilities/stringutils.o utilities/gtk/logging.o utilities/compat.o
 UTILS=irchack modbot
 ifdef GTK_LIBS
 ifdef AVCODEC_LIBS
@@ -30,6 +30,12 @@ ifdef SWSCALE_LIBS
   ifdef LIBV4L2_LIBS
     CFLAGS+=-DHAVE_V4L2 $(LIBV4L2_CFLAGS)
   endif
+  ifneq ($(findstring MINGW,$(shell uname -s)),)
+    LDFLAGS+=-mwindows
+    windowstargets: camviewer tc_client-gtk
+ @echo
+ @echo 'To build the core (tc_client.exe), enter this directory from cygwin and type make'
+  endif
 endif
 endif
 endif
diff --git a/utilities/camviewer/camviewer.c b/utilities/camviewer/camviewer.c
index ac52f75..9bbe689 100644
--- a/utilities/camviewer/camviewer.c
+++ b/utilities/camviewer/camviewer.c
@@ -18,7 +18,12 @@
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/prctl.h>
+#ifdef _WIN32
+  #include <wtypes.h>
+  #include <winbase.h>
+#else
+  #include <sys/prctl.h>
+#endif
 #include <libavcodec/avcodec.h>
 #include <libswscale/swscale.h>
 #if LIBAVUTIL_VERSION_MAJOR>50 || (LIBAVUTIL_VERSION_MAJOR==50 && LIBAVUTIL_VERSION_MINOR>37)
@@ -40,6 +45,7 @@
   #include <libv4l2.h>
   #include <linux/videodev2.h>
 #endif
+#include "../compat.h"
 
 #if GTK_MAJOR_VERSION==2
   #define GTK_ORIENTATION_HORIZONTAL 0
@@ -55,6 +61,14 @@
   }
 #endif
 
+#ifdef _WIN32
+SECURITY_ATTRIBUTES sa={
+  .nLength=sizeof(SECURITY_ATTRIBUTES),
+  .bInheritHandle=1,
+  .lpSecurityDescriptor=0
+};
+#endif
+
 struct camera
 {
   AVFrame* frame;
@@ -146,10 +160,12 @@ char buf[1024];
 gboolean handledata(GIOChannel* channel, GIOCondition condition, gpointer datap)
 {
   struct viddata* data=datap;
+  gsize r;
   unsigned int i;
   for(i=0; i<1023; ++i)
   {
-    if(read(tc_client[0], &buf[i], 1)<1){printf("No more data\n"); gtk_main_quit(); return 0;}
+    g_io_channel_read_chars(channel, &buf[i], 1, &r, 0);
+    if(r<1){printf("No more data\n"); gtk_main_quit(); return 0;}
     if(buf[i]=='\r'||buf[i]=='\n'){break;}
   }
   buf[i]=0;
@@ -246,7 +262,7 @@ gboolean handledata(GIOChannel* channel, GIOCondition condition, gpointer datap)
     unsigned int size=strtoul(&sizestr[1], 0, 0);
     if(!size){return 1;}
     unsigned char frameinfo;
-    read(tc_client[0], &frameinfo, 1);
+    g_io_channel_read_chars(channel, (gchar*)&frameinfo, 1, 0, 0);
     --size; // For the byte we read above
     AVPacket pkt;
     av_init_packet(&pkt);
@@ -256,7 +272,8 @@ gboolean handledata(GIOChannel* channel, GIOCondition condition, gpointer datap)
     unsigned int pos=0;
     while(pos<size)
     {
-      pos+=read(tc_client[0], pkt.data+pos, size-pos);
+      g_io_channel_read_chars(channel, (gchar*)pkt.data+pos, size-pos, &r, 0);
+      pos+=r;
     }
 #if defined(HAVE_AVRESAMPLE) || defined(HAVE_SWRESAMPLE)
     // Find the camera representation for the given ID (for decoder context)
@@ -297,13 +314,14 @@ gboolean handledata(GIOChannel* channel, GIOCondition condition, gpointer datap)
   unsigned char databuf[size+4];
   pkt.data=databuf;
   unsigned char frameinfo;
-  read(tc_client[0], &frameinfo, 1);
+  g_io_channel_read_chars(channel, (gchar*)&frameinfo, 1, 0, 0);
 // printf("Frametype-frame: %x\n", ((unsigned int)frameinfo&0xf0)/16);
 // printf("Frametype-codec: %x\n", (unsigned int)frameinfo&0xf);
   unsigned int pos=0;
   while(pos<size)
   {
-    pos+=read(tc_client[0], pkt.data+pos, size-pos);
+    g_io_channel_read_chars(channel, (gchar*)pkt.data+pos, size-pos, &r, 0);
+    pos+=r;
   }
   if((frameinfo&0xf)!=2){return 1;} // Not FLV1, get data but discard it
   if(!cam){printf("No cam found with ID '%s'\n", &buf[7]); return 1;}
@@ -496,6 +514,29 @@ int main(int argc, char** argv)
 #endif
   gtk_widget_show_all(w);
 
+  unsigned int i;
+#ifdef _WIN32
+  HANDLE h_tc_client0, h_tc_client1;
+  CreatePipe(&h_tc_client0, &h_tc_client1, &sa, 0);
+  HANDLE h_tc_client_in0, h_tc_client_in1;
+  CreatePipe(&h_tc_client_in0, &h_tc_client_in1, &sa, 0);
+  tc_client[0]=_open_osfhandle(h_tc_client0, _O_RDONLY);
+  tc_client[1]=_open_osfhandle(h_tc_client1, _O_WRONLY);
+  tc_client_in[0]=_open_osfhandle(h_tc_client_in0, _O_RDONLY);
+  tc_client_in[1]=_open_osfhandle(h_tc_client_in1, _O_WRONLY);
+  STARTUPINFO startup;
+  GetStartupInfo(&startup);
+  startup.dwFlags|=STARTF_USESTDHANDLES;
+  startup.hStdInput=h_tc_client_in0;
+  startup.hStdOutput=h_tc_client1;
+  PROCESS_INFORMATION pi;
+  int len=strlen("./tc_client");
+  for(i=1; i<argc; ++i){len+=strlen(argv[i])+1;}
+  char cmd[len+1];
+  strcpy(cmd, "./tc_client");
+  for(i=1; i<argc; ++i){strcat(cmd, " "); strcat(cmd, argv[i]);}
+  CreateProcess(0, cmd, 0, 0, 1, DETACHED_PROCESS, 0, 0, &startup, &pi);
+#else
   pipe(tc_client);
   pipe(tc_client_in);
   if(!fork())
@@ -508,6 +549,7 @@ int main(int argc, char** argv)
     argv[0]=(strncmp(argv[0], "./", 2)?"tc_client":"./tc_client");
     execvp(argv[0], argv);
   }
+#endif
   close(tc_client_in[0]);
   GIOChannel* tcchannel=g_io_channel_unix_new(tc_client[0]);
   g_io_channel_set_encoding(tcchannel, 0, 0);
@@ -515,9 +557,11 @@ int main(int argc, char** argv)
 
   gtk_main();
  
+#ifdef _WIN32
+  TerminateProcess(pi.hProcess, 0);
+#endif
   g_source_remove(channel_id);
   g_io_channel_shutdown(tcchannel, 0, 0);
-  unsigned int i;
   for(i=0; i<data.camcount; ++i)
   {
     av_frame_free(&data.cams[i].frame);
diff --git a/utilities/compat.c b/utilities/compat.c
index e620559..ba15f60 100644
--- a/utilities/compat.c
+++ b/utilities/compat.c
@@ -15,8 +15,10 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include "compat.h"
-#ifdef __ANDROID__
-// Android has no dprintf, so we make our own
+#if defined(__ANDROID__) || defined(_WIN32)
+// Android and windows have no dprintf, so we make our own
+#include <stdio.h>
+#include <unistd.h>
 #include <stdarg.h>
 size_t dprintf(int fd, const char* fmt, ...)
 {
diff --git a/utilities/compat.h b/utilities/compat.h
index 2cfb39b..f635886 100644
--- a/utilities/compat.h
+++ b/utilities/compat.h
@@ -14,8 +14,16 @@
     You should have received a copy of the GNU Affero General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
-#ifdef __ANDROID__
+#if defined(__ANDROID__) || defined(_WIN32)
 #include <stdint.h>
+#include <stddef.h>
 extern size_t dprintf(int fd, const char* fmt, ...);
 #define mbtowc(x,y,z) 1
 #endif
+#ifdef _WIN32
+  #define prctl(...)
+  #define wait(x)
+#endif
+#if GLIB_MAJOR_VERSION<2 || (GLIB_MAJOR_VERSION==2 && GLIB_MINOR_VERSION<2)
+  #define g_io_channel_read_chars(a,b,c,d,e) g_io_channel_read(a,b,c,d)
+#endif
diff --git a/utilities/gtk/camviewer.c b/utilities/gtk/camviewer.c
index c5a7514..037f41a 100644
--- a/utilities/gtk/camviewer.c
+++ b/utilities/gtk/camviewer.c
@@ -19,7 +19,13 @@
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/prctl.h>
+#ifdef _WIN32
+  #include <wtypes.h>
+  #include <winbase.h>
+#else
+  #include <sys/prctl.h>
+  #include <sys/wait.h>
+#endif
 #include <ctype.h>
 #include <libavcodec/avcodec.h>
 #include <libswscale/swscale.h>
@@ -50,6 +56,7 @@
 #include "gui.h"
 #include "logging.h"
 #include "../stringutils.h"
+#include "../compat.h"
 
 struct viddata
 {
@@ -78,6 +85,9 @@ const char* mycolor=0;
 char* nickname=0;
 char frombuild=0; // Running from the build directory
 #define TC_CLIENT (frombuild?"./tc_client":"tc_client")
+#ifdef _WIN32
+  PROCESS_INFORMATION coreprocess={.hProcess=0};
+#endif
 
 void updatescaling(struct viddata* data, unsigned int width, unsigned int height)
 {
@@ -148,11 +158,12 @@ void printchat_color(struct viddata* data, const char* text, const char* color,
 char buf[1024];
 gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer datap)
 {
-  int fd=g_io_channel_unix_get_fd(iochannel);
+  gsize r;
   unsigned int i;
   for(i=0; i<1023; ++i)
   {
-    if(read(fd, &buf[i], 1)<1){printf("No more data\n"); gtk_main_quit(); return 0;}
+    g_io_channel_read_chars(iochannel, &buf[i], 1, &r, 0);
+    if(r<1){printf("No more data\n"); gtk_main_quit(); return 0;}
     if(buf[i]=='\r'||buf[i]=='\n'){break;}
   }
   buf[i]=0;
@@ -222,6 +233,7 @@ gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer data
     if(space[-1]==':')
     {
 // TODO: handle /msg (PMs)
+#ifndef _WIN32 // TODO: port sound and youtube command code to windows
       if(config_get_bool("soundradio_cmd") && !fork())
       {
         execlp("sh", "sh", "-c", config_get_str("soundcmd"), (char*)0);
@@ -229,7 +241,7 @@ gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer data
       }
       if(!strncmp(space, " /mbs youTube ", 14) && config_get_bool("youtuberadio_cmd") && !fork())
       {
-// TODO: store the PID and make sure it's dead before starting a new video?
+// TODO: store the PID and make sure it's dead before starting a new video? and upon /mbc?
 // TODO: only play videos from mods?
         char* id=&space[14];
         char* offset=strchr(id, ' ');
@@ -256,6 +268,7 @@ gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer data
         execlp("sh", "sh", "-c", cmd, (char*)0);
         _exit(0);
       }
+#endif
     }
 // TODO: handle logging PMs
     if(config_get_bool("enable_logging")){logger_write(buf, channel, 0);}
@@ -405,7 +418,7 @@ gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer data
     unsigned int size=strtoul(&sizestr[1], 0, 0);
     if(!size){return 1;}
     unsigned char frameinfo;
-    read(fd, &frameinfo, 1);
+    g_io_channel_read_chars(iochannel, (gchar*)&frameinfo, 1, 0, 0);
     --size; // For the byte we read above
     AVPacket pkt;
     av_init_packet(&pkt);
@@ -415,7 +428,8 @@ gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer data
     unsigned int pos=0;
     while(pos<size)
     {
-      pos+=read(fd, pkt.data+pos, size-pos);
+      g_io_channel_read_chars(iochannel, (gchar*)pkt.data+pos, size-pos, &r, 0);
+      pos+=r;
     }
 #if defined(HAVE_AVRESAMPLE) || defined(HAVE_SWRESAMPLE)
     // Find the camera representation for the given ID (for decoder context)
@@ -448,13 +462,14 @@ gboolean handledata(GIOChannel* iochannel, GIOCondition condition, gpointer data
   unsigned char databuf[size+4];
   pkt.data=databuf;
   unsigned char frameinfo;
-  read(fd, &frameinfo, 1);
+  g_io_channel_read_chars(iochannel, (gchar*)&frameinfo, 1, 0, 0);
 // printf("Frametype-frame: %x\n", ((unsigned int)frameinfo&0xf0)/16);
 // printf("Frametype-codec: %x\n", (unsigned int)frameinfo&0xf);
   unsigned int pos=0;
   while(pos<size)
   {
-    pos+=read(fd, pkt.data+pos, size-pos);
+    g_io_channel_read_chars(iochannel, (gchar*)pkt.data+pos, size-pos, &r, 0);
+    pos+=r;
   }
   if(!strcmp(&buf[7], "out"))
   {
@@ -608,7 +623,9 @@ gboolean handleresize(GtkWidget* widget, GdkEventConfigure* event, struct viddat
   {
     updatescaling(data, event->width, 0);
   }
+#ifndef _WIN32 // For some reason scrolling as a response to resizing freezes windows
   if(bottom){autoscroll_after(data->scroll);}
+#endif
   return 0;
 }
 
@@ -616,7 +633,9 @@ void handleresizepane(GObject* obj, GParamSpec* spec, struct viddata* data)
 {
   char bottom=autoscroll_before(data->scroll);
   updatescaling(data, 0, gtk_paned_get_position(GTK_PANED(obj)));
+#ifndef _WIN32
   if(bottom){autoscroll_after(data->scroll);}
+#endif
 }
 
 gboolean inputkeys(GtkWidget* widget, GdkEventKey* event, void* data)
@@ -741,6 +760,36 @@ void startsession(GtkButton* button, void* x)
   if(!chanpass[0]){chanpass=gtk_entry_get_text(GTK_ENTRY(gtk_builder_get_object(gui, "cc_password")));}
   const char* acc_user=gtk_entry_get_text(GTK_ENTRY(gtk_builder_get_object(gui, "acc_username")));
   const char* acc_pass=gtk_entry_get_text(GTK_ENTRY(gtk_builder_get_object(gui, "acc_password")));
+#ifdef _WIN32
+  HANDLE h_tc_client0, h_tc_client1;
+  CreatePipe(&h_tc_client0, &h_tc_client1, &sa, 0);
+  HANDLE h_tc_client_in0, h_tc_client_in1;
+  CreatePipe(&h_tc_client_in0, &h_tc_client_in1, &sa, 0);
+  tc_client[0]=_open_osfhandle(h_tc_client0, _O_RDONLY);
+  tc_client[1]=_open_osfhandle(h_tc_client1, _O_WRONLY);
+  tc_client_in[0]=_open_osfhandle(h_tc_client_in0, _O_RDONLY);
+  tc_client_in[1]=_open_osfhandle(h_tc_client_in1, _O_WRONLY);
+  STARTUPINFO startup;
+  GetStartupInfo(&startup);
+  startup.dwFlags|=STARTF_USESTDHANDLES;
+  startup.hStdInput=h_tc_client_in0;
+  startup.hStdOutput=h_tc_client1;
+  char cmd[strlen("./tc_client -u    0")+strlen(acc_user)+strlen(channel)+strlen(nick)+strlen(chanpass)];
+  strcpy(cmd, "./tc_client ");
+  if(acc_user[0])
+  {
+    strcat(cmd, "-u ");
+    strcat(cmd, acc_user);
+    strcat(cmd, " ");
+  }
+  strcat(cmd, channel);
+  strcat(cmd, " ");
+  strcat(cmd, nick);
+  strcat(cmd, " ");
+  strcat(cmd, chanpass);
+  strcat(cmd, " ");
+  CreateProcess(0, cmd, 0, 0, 1, DETACHED_PROCESS, 0, 0, &startup, &coreprocess);
+#else
   pipe(tc_client);
   pipe(tc_client_in);
   if(!fork())
@@ -757,6 +806,7 @@ void startsession(GtkButton* button, void* x)
       execlp(TC_CLIENT, TC_CLIENT, channel, nick, chanpass, (char*)0);
     }
   }
+#endif
   if(acc_user[0]){dprintf(tc_client_in[1], "%s\n", acc_pass);}
   write(tc_client_in[1], "/color\n", 7);
   GIOChannel* tcchannel=g_io_channel_unix_new(tc_client[0]);
@@ -772,7 +822,11 @@ int main(int argc, char** argv)
   avcodec_register_all();
   data->vdecoder=avcodec_find_decoder(AV_CODEC_ID_FLV1);
   data->adecoder=avcodec_find_decoder(AV_CODEC_ID_NELLYMOSER);
+#ifndef _WIN32
   signal(SIGCHLD, SIG_IGN);
+#else
+  frombuild=1;
+#endif
 
 #if defined(HAVE_AVRESAMPLE) || defined(HAVE_SWRESAMPLE)
   #ifdef HAVE_AVRESAMPLE
@@ -913,6 +967,12 @@ int main(int argc, char** argv)
 
   gtk_main();
  
+#ifdef _WIN32
+  if(coreprocess.hProcess)
+  {
+    TerminateProcess(coreprocess.hProcess, 0);
+  }
+#endif
   camera_cleanup();
 #ifdef HAVE_AVRESAMPLE
   avresample_free(&data->resamplectx);
diff --git a/utilities/gtk/compat.c b/utilities/gtk/compat.c
index 3f2efd4..8d37d3d 100644
--- a/utilities/gtk/compat.c
+++ b/utilities/gtk/compat.c
@@ -22,6 +22,14 @@
 #include <gtk/gtk.h>
 #include "compat.h"
 
+#ifdef _WIN32
+SECURITY_ATTRIBUTES sa={
+  .nLength=sizeof(SECURITY_ATTRIBUTES),
+  .bInheritHandle=1,
+  .lpSecurityDescriptor=0
+};
+#endif
+
 #if GTK_MAJOR_VERSION<3
   GtkWidget* gtk_box_new(int vertical, int spacing)
   {
@@ -92,4 +100,11 @@
     if(!gtk_builder_add_from_string(gui, buf, -1, &error)){g_error("%s\n", error->message);}
     return gui;
   }
+#elif GTK_MAJOR_VERSION==3 && GTK_MINOR_VERSION<10
+  GtkBuilder* gtk_builder_new_from_file(const char* filename)
+  {
+    GtkBuilder* gui=gtk_builder_new();
+    gtk_builder_add_from_file(gui, filename, 0);
+    return gui;
+  }
 #endif
diff --git a/utilities/gtk/compat.h b/utilities/gtk/compat.h
index a0a5ee2..cd61c08 100644
--- a/utilities/gtk/compat.h
+++ b/utilities/gtk/compat.h
@@ -14,14 +14,18 @@
     You should have received a copy of the GNU Affero General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
+#ifdef _WIN32
+#include <wtypes.h>
+extern SECURITY_ATTRIBUTES sa;
+#endif
 #if GTK_MAJOR_VERSION<3
   #define GTK_ORIENTATION_HORIZONTAL 0
   #define GTK_ORIENTATION_VERTICAL 1
   extern GtkWidget* gtk_box_new(int vertical, int spacing);
   extern int gtk_widget_get_allocated_width(GtkWidget* widget);
   extern int gtk_widget_get_allocated_height(GtkWidget* widget);
-  extern GtkBuilder* gtk_builder_new_from_file(const char* filename);
 #endif
-#if GTK_MAJOR_VERSION<3 || GTK_MINOR_VERSION<10
+#if GTK_MAJOR_VERSION<3 || (GTK_MAJOR_VERSION==3 && GTK_MINOR_VERSION<10)
   #define gtk_button_new_from_icon_name(name, size) gtk_button_new_from_stock(name)
+  extern GtkBuilder* gtk_builder_new_from_file(const char* filename);
 #endif
diff --git a/utilities/gtk/config.c b/utilities/gtk/config.c
index 7d5a813..d14ac6e 100644
--- a/utilities/gtk/config.c
+++ b/utilities/gtk/config.c
@@ -31,9 +31,13 @@ unsigned int configitemcount=0;
 
 void config_load(void)
 {
+#ifndef _WIN32
   const char* home=getenv("HOME");
   char filename[strlen(home)+strlen("/.config/tc_client-gtk0")];
   sprintf(filename, "%s/.config/tc_client-gtk", home);
+#else
+  char* filename="config.txt";
+#endif
   FILE* f=fopen(filename, "r");
   if(!f){return;}
   char buf[2048];
@@ -55,11 +59,15 @@ void config_load(void)
 
 void config_save(void)
 {
+#ifndef _WIN32
   const char* home=getenv("HOME");
   char filename[strlen(home)+strlen("/.config/tc_client-gtk0")];
   sprintf(filename, "%s/.config", home);
   mkdir(filename, 0700);
   strcat(filename, "/tc_client-gtk");
+#else
+  char* filename="config.txt";
+#endif
   FILE* f=fopen(filename, "w");
   if(!f){perror("fopen(~/.config/tc_client-gtk)"); return;}
   unsigned int i;
diff --git a/utilities/gtk/gui.c b/utilities/gtk/gui.c
index ded7028..dad17fe 100644
--- a/utilities/gtk/gui.c
+++ b/utilities/gtk/gui.c
@@ -16,6 +16,7 @@
 */
 #include <stdlib.h>
 #include <string.h>
+#include <stdint.h>
 #include <gtk/gtk.h>
 #include "gui.h"
 #include "config.h"