| tvkaista-0.979/tvkaista_gtkui.c | | tvkaista-0.981/tvkaista_gtkui.c |
| 45 | #include <string.h> | 45 | #include <string.h> |
| 46 | #include <ctype.h> | 46 | #include <ctype.h> |
| 47 | | 47 | |
| | 48 | #include <signal.h> |
| 48 | #include <sys/types.h> | 49 | #include <sys/types.h> |
| 49 | #include <sys/stat.h> | 50 | #include <sys/stat.h> |
| | 51 | #include <sys/wait.h> |
| 50 | #include <fcntl.h> | 52 | #include <fcntl.h> |
| 51 | | 53 | |
| 52 | #include <errno.h> | 54 | #include <errno.h> |
| 122 | int abspos; | 124 | int abspos; |
| 123 | int refindx; | 125 | int refindx; |
| 124 | char daytime[8]; | 126 | char daytime[8]; |
| | 127 | bool (*childexit_cb)(void); |
| 125 | } G; | 128 | } G; |
| 126 | | 129 | |
| 127 | /* widgets in separate structure, for code readability */ | 130 | /* widgets in separate structure, for code readability */ |
| 148 | G.prgfd[i] = -1; | 151 | G.prgfd[i] = -1; |
| 149 | G.abspos = 0; G.refindx = -1; | 152 | G.abspos = 0; G.refindx = -1; |
| 150 | } | 153 | } |
| | 154 | |
| | 155 | static void sigact(int sig, void (*handler)(int)) |
| | 156 | { |
| | 157 | struct sigaction action; |
| | 158 | |
| | 159 | action.sa_handler = handler; |
| | 160 | action.sa_flags = SA_RESTART|SA_NOCLDSTOP; /* NOCLDSTOP needed if ptraced */ |
| | 161 | sigemptyset(&action.sa_mask); |
| | 162 | sigaction(sig, &action, NULL); |
| | 163 | } |
| | 164 | |
| | 165 | static void childexit(int sig) |
| | 166 | { |
| | 167 | (void)sig; |
| | 168 | while (waitpid(-1, NULL, WNOHANG) > 0) |
| | 169 | ; |
| | 170 | if (G.childexit_cb) |
| | 171 | G.childexit_cb(); |
| | 172 | } |
| | 173 | |
| | 174 | bool clear_childexit_cb(void) |
| | 175 | { |
| | 176 | G.childexit_cb = null; |
| | 177 | return false; |
| | 178 | } |
| | 179 | |
| | 180 | void execbgcommand(const char * command, char * const argv[]) |
| | 181 | { |
| | 182 | switch(fork()) |
| | 183 | { |
| | 184 | case 0: |
| | 185 | /* child */ |
| | 186 | break; |
| | 187 | case -1: |
| | 188 | /* failure */ |
| | 189 | die("fork() failed:"); /* XXX */ |
| | 190 | default: |
| | 191 | /*parent */ |
| | 192 | G.childexit_cb = clear_childexit_cb; // default |
| | 193 | return; |
| | 194 | } |
| | 195 | (void)execvp(command, argv); |
| | 196 | die("execvp() failed:"); |
| | 197 | } |
| | 198 | |
| | 199 | void runbgcommand(const char * command, const char * s, ...) |
| | 200 | { |
| | 201 | char buffer[128]; |
| | 202 | char * argv[10]; |
| | 203 | char * p = buffer; |
| | 204 | int ai = 1; |
| | 205 | va_list ap; |
| | 206 | |
| | 207 | va_start(ap, s); |
| | 208 | |
| | 209 | strcpy(p, command); |
| | 210 | argv[0] = p; |
| | 211 | p += strlen(p) + 1; |
| | 212 | while (s) { |
| | 213 | // XXX better format string checker later ? |
| | 214 | if (s[0] == '%' && s[1] != '\0' && s[2] == '\0') { |
| | 215 | const char * str = va_arg(ap, const char *); |
| | 216 | sprintf(p, s, str); |
| | 217 | } |
| | 218 | else strcpy(p, s); |
| | 219 | argv[ai++] = p; |
| | 220 | p += strlen(p) + 1; |
| | 221 | s = va_arg(ap, const char *); |
| | 222 | } |
| | 223 | argv[ai] = null; |
| | 224 | execbgcommand(command, argv); |
| | 225 | } |
| | 226 | |
| 151 | | 227 | |
| 152 | FILE * runhelper(const char * format, ...) | 228 | FILE * runhelper(const char * format, ...) |
| 153 | { | 229 | { |
| 825 | G.maxchannelindex = 0; | 901 | G.maxchannelindex = 0; |
| 826 | } | 902 | } |
| 827 | | 903 | |
| 828 | bool reset_signal(void * inprogress_p) | 904 | bool relist_view_cb(void); |
| | 905 | void update_pressed(void * uu) |
| 829 | { | 906 | { |
| 830 | *(int*)inprogress_p = false; | 907 | (void)uu; |
| | 908 | |
| | 909 | if (G.childexit_cb) { |
| | 910 | ModalMessageDialog("edellinen toiminto ajossa"); |
| | 911 | return; |
| | 912 | } |
| | 913 | |
| | 914 | runbgcommand(G_helper, "gui", "update"); |
| | 915 | G.childexit_cb = relist_view_cb; |
| | 916 | } |
| | 917 | |
| | 918 | bool relist_view(void); |
| | 919 | bool relist_view_cb(void) |
| | 920 | { |
| | 921 | g_idle_add(relist_view, null); |
| 831 | return false; | 922 | return false; |
| 832 | } | 923 | } |
| 833 | | 924 | |
| 834 | void update_pressed(void * uu) | 925 | bool relist_view(void) |
| 835 | { | 926 | { |
| 836 | static int inprogress = false; | | |
| 837 | (void)uu; | | |
| 838 | | | |
| 839 | if (inprogress) // XXX what if reset_signal() never called ?? | | |
| 840 | return; | | |
| 841 | | | |
| 842 | gtk_tree_view_set_model(GTK_TREE_VIEW(W.listview), null); | 927 | gtk_tree_view_set_model(GTK_TREE_VIEW(W.listview), null); |
| 843 | FILE * fh = runhelper("update"); | 928 | FILE * fh = runhelper("list"); |
| 844 | clean_data(); | 929 | clean_data(); |
| 845 | if (fill_store(fh)) { | 930 | if (fill_store(fh)) { |
| 846 | inprogress = true; | 931 | g_idle_add(clear_childexit_cb, null); |
| 847 | g_idle_add(reset_signal, &inprogress); | | |
| 848 | } | 932 | } |
| 849 | pclose(fh); | 933 | pclose(fh); |
| 850 | gtk_tree_view_set_model(GTK_TREE_VIEW(W.listview), | 934 | gtk_tree_view_set_model(GTK_TREE_VIEW(W.listview), |
| 851 | GTK_TREE_MODEL(W.listmodel)); | 935 | GTK_TREE_MODEL(W.listmodel)); |
| | 936 | return false; |
| 852 | } | 937 | } |
| 853 | | 938 | |
| 854 | void handle_program(const char * tool) | 939 | void handle_program(const char * tool) |
| 867 | return; | 952 | return; |
| 868 | } | 953 | } |
| 869 | | 954 | |
| 870 | pclose(runhelper("play %s %d %s", tool, | 955 | runbgcommand(G_helper, "gui", "play", tool, |
| 871 | custom_list_get_id(W.listmodel, G.indx), | 956 | "%d", custom_list_get_id(W.listmodel, G.indx), |
| 872 | speeds[speed])); | 957 | speeds[speed], null); |
| 873 | } | 958 | } |
| 874 | | 959 | |
| 875 | void play_pressed(void * uu) | 960 | void play_pressed(void * uu) |
| 876 | { | 961 | { |
| 877 | (void)uu; | 962 | (void)uu; |
| 878 | | 963 | |
| | 964 | if (G.childexit_cb) { |
| | 965 | ModalMessageDialog("edellinen toiminto ajossa"); |
| | 966 | return; |
| | 967 | } |
| 879 | gint indx = gtk_combo_box_get_active(GTK_COMBO_BOX(W.pcb)); | 968 | gint indx = gtk_combo_box_get_active(GTK_COMBO_BOX(W.pcb)); |
| 880 | | 969 | |
| 881 | if (indx < 0) { | 970 | if (indx < 0) { |
| 889 | void save_pressed(void * uu) | 978 | void save_pressed(void * uu) |
| 890 | { | 979 | { |
| 891 | (void)uu; | 980 | (void)uu; |
| | 981 | |
| | 982 | if (G.childexit_cb) { |
| | 983 | ModalMessageDialog("edellinen toiminto ajossa"); |
| | 984 | return; |
| | 985 | } |
| 892 | handle_program("wget"); | 986 | handle_program("wget"); |
| 893 | } | 987 | } |
| 894 | | 988 | |
| 992 | "Tallenteiden sijaintipaikka on $HOME/.tvkaista/tallenteet/.\n" | 1086 | "Tallenteiden sijaintipaikka on $HOME/.tvkaista/tallenteet/.\n" |
| 993 | "\n"; | 1087 | "\n"; |
| 994 | | 1088 | |
| | 1089 | static void setsighandlers(void) |
| | 1090 | { |
| | 1091 | sigact(SIGPIPE, SIG_IGN); |
| | 1092 | sigact(SIGIO, SIG_IGN); |
| | 1093 | sigact(SIGCHLD, childexit); |
| | 1094 | |
| | 1095 | /* Now cleanup possible when these signals arrive... */ |
| | 1096 | //sigact(SIGTERM, my_exit); |
| | 1097 | //sigact(SIGHUP, my_exit); |
| | 1098 | } |
| | 1099 | |
| 995 | int main(int argc, char *argv[]) | 1100 | int main(int argc, char *argv[]) |
| 996 | { | 1101 | { |
| 997 | setpgid(0, 0); | 1102 | setpgid(0, 0); |
| 999 | gtk_init(&argc, &argv); | 1104 | gtk_init(&argc, &argv); |
| 1000 | setenv("PERL_UNICODE", "SD", 1); | 1105 | setenv("PERL_UNICODE", "SD", 1); |
| 1001 | write(1, intro, sizeof intro - 1); | 1106 | write(1, intro, sizeof intro - 1); |
| | 1107 | setsighandlers(); |
| 1002 | gui(); | 1108 | gui(); |
| 1003 | gtk_main(); | 1109 | gtk_main(); |
| 1004 | return 0; | 1110 | return 0; |