You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 lines
5.7KB

  1. /*
  2. * SpaceAPI based panel applet for UNIX using GTK2
  3. *
  4. * Author: hanez <you@hanez.org>
  5. * Contributors: Haeger, atari, beh and eisbaer
  6. *
  7. * License (Beerware License):
  8. * As long as you retain this notice you can do whatever you want with this
  9. * stuff. If we meet some day, and you think this stuff is worth it, you can buy
  10. * me a beer in return hanez and all other contributers
  11. *
  12. * TODO:
  13. * - Add door open/close date to notification and status
  14. * - Fix: not show notification twice at start when status "open"
  15. */
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <stdbool.h>
  19. #include <time.h>
  20. #include <curl/curl.h>
  21. #include <gtk/gtk.h>
  22. #include <gdk-pixbuf/gdk-pixdata.h>
  23. #include <json.h>
  24. #if LIBNOTIFY
  25. #include <libnotify/notify.h>
  26. #endif
  27. #include "pesthoernchen.h"
  28. struct string {
  29. char *ptr;
  30. size_t len;
  31. };
  32. static char *name = "Dooris for UNIX";
  33. static char *statusurl = "https://www.hamburg.ccc.de/dooris/status.json";
  34. static char *agent = "Dooris-for-UNIX/0.42";
  35. // The delay for polling the dooris service. Adjust this before compiling
  36. int delay = 900000; // ms. aka 15 minutes
  37. bool door_open = false;
  38. bool old_door_open = false;
  39. GtkStatusIcon *tray_icon;
  40. bool do_it();
  41. void invoke_notification();
  42. void init_string(struct string *s) {
  43. s->len = 0;
  44. s->ptr = malloc(s->len+1);
  45. if (s->ptr == NULL) {
  46. fprintf(stderr, "malloc() failed\n");
  47. exit(EXIT_FAILURE);
  48. }
  49. s->ptr[0] = '\0';
  50. }
  51. size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s) {
  52. size_t new_len = s->len + size*nmemb;
  53. s->ptr = realloc(s->ptr, new_len+1);
  54. if (s->ptr == NULL) {
  55. fprintf(stderr, "realloc() failed\n");
  56. exit(EXIT_FAILURE);
  57. }
  58. memcpy(s->ptr+s->len, ptr, size*nmemb);
  59. s->ptr[new_len] = '\0';
  60. s->len = new_len;
  61. return size*nmemb;
  62. }
  63. void tray_icon_on_click(GtkStatusIcon *status_icon, gpointer user_data) {
  64. do_it();
  65. }
  66. void get_bouncer_data() {
  67. CURL *curl;
  68. CURLcode res;
  69. struct json_object *response_json_object;
  70. struct json_object *door_json_object;
  71. struct json_object *leaf_json_object;
  72. bool door_status;
  73. int door_last_change;
  74. struct string s;
  75. printf("Called get_bouncer_data()\n");
  76. old_door_open = door_open;
  77. init_string(&s);
  78. curl = curl_easy_init();
  79. if(!curl) {
  80. fprintf(stderr, "curl_easy_init() failed.\n");
  81. return;
  82. }
  83. curl_easy_setopt(curl, CURLOPT_URL, statusurl);
  84. curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
  85. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
  86. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
  87. curl_easy_setopt(curl, CURLOPT_USERAGENT, agent);
  88. res = curl_easy_perform(curl);
  89. curl_easy_cleanup(curl);
  90. if(res != CURLE_OK) {
  91. fprintf(stderr, "curl_easy_perform() failed: %s\n",
  92. curl_easy_strerror(res));
  93. return;
  94. }
  95. response_json_object = json_tokener_parse(s.ptr);
  96. free(s.ptr);
  97. // door objects
  98. door_json_object = json_object_object_get(response_json_object, "state");
  99. leaf_json_object = json_object_object_get(door_json_object, "open");
  100. door_status = json_object_get_int(leaf_json_object);
  101. //door_status = true;
  102. leaf_json_object = json_object_object_get(door_json_object, "lastchange");
  103. door_last_change = json_object_get_int(leaf_json_object);
  104. // free door object
  105. json_object_put(door_json_object);
  106. // free leaf object
  107. //json_object_put(leaf_json_object);
  108. // free response object
  109. // json_object_put(response_json_object);
  110. printf("Door status: = %d\n", door_status);
  111. printf("Door last change: = %d\n", door_last_change);
  112. if (door_status == true) {
  113. door_open = true;
  114. } else {
  115. door_open = false;
  116. }
  117. }
  118. void invoke_notification() {
  119. char door[20];
  120. if (door_open == true) {
  121. snprintf(door, 20, "Door open...");
  122. } else {
  123. snprintf(door, 20, "Door closed...");
  124. }
  125. gtk_status_icon_set_tooltip(tray_icon, door);
  126. #if LIBNOTIFY
  127. NotifyNotification *n;
  128. notify_init(name);
  129. n = notify_notification_new(name, door, NULL);
  130. //notify_notification_set_timeout(n, 10000);
  131. if (door_open == true) {
  132. notify_notification_set_icon_from_pixbuf(n, gdk_pixbuf_from_pixdata(
  133. &icon_yellow_pixbuf,
  134. true,
  135. NULL));
  136. } else {
  137. notify_notification_set_icon_from_pixbuf(n, gdk_pixbuf_from_pixdata(
  138. &icon_red_pixbuf,
  139. true,
  140. NULL));
  141. }
  142. notify_notification_show(n, NULL);
  143. g_object_unref(G_OBJECT(n));
  144. #endif
  145. }
  146. void set_status() {
  147. if (door_open == true) {
  148. printf("Set to status: open\n");
  149. gtk_status_icon_set_from_pixbuf(tray_icon,
  150. gdk_pixbuf_from_pixdata(&icon_yellow_pixbuf,
  151. true,
  152. NULL));
  153. } else {
  154. printf("Set to status: closed\n");
  155. gtk_status_icon_set_from_pixbuf(tray_icon,
  156. gdk_pixbuf_from_pixdata(&icon_red_pixbuf,
  157. true,
  158. NULL));
  159. }
  160. }
  161. bool do_it() {
  162. get_bouncer_data();
  163. set_status();
  164. if (door_open != old_door_open) {
  165. invoke_notification();
  166. }
  167. return true;
  168. }
  169. int main(int argc, char **argv) {
  170. gtk_init(&argc, &argv);
  171. tray_icon = gtk_status_icon_new();
  172. g_signal_connect(G_OBJECT(tray_icon), "activate",
  173. G_CALLBACK(tray_icon_on_click), NULL);
  174. gtk_status_icon_set_visible(tray_icon, true);
  175. do_it();
  176. // DEBUG STUFF
  177. //door_open = true;
  178. //set_status();
  179. // END DEBUG STUFF
  180. invoke_notification();
  181. gtk_timeout_add(delay, (GtkFunction)do_it, (gpointer)NULL);
  182. gtk_main();
  183. return 0;
  184. }