PageRenderTime 60ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/lcdproc-0.5.5/clients/lcdproc/chrono.c

#
C | 498 lines | 296 code | 78 blank | 124 comment | 58 complexity | a17f5bbeb680abbf9caf91386d97532b MD5 | raw file
Possible License(s): GPL-2.0, CC-BY-SA-3.0
  1. /** \file clients/lcdproc/chrono.c
  2. * Implements the 'OldTime', 'TimeDate', 'Uptime', 'MiniClock', and 'BigClock'
  3. * screens.
  4. */
  5. /*-
  6. * This file is part of lcdproc, the lcdproc client.
  7. *
  8. * This file is released under the GNU General Public License.
  9. * Refer to the COPYING file distributed with this package.
  10. */
  11. #include <sys/types.h>
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <unistd.h>
  16. #include <fcntl.h>
  17. #include <sys/utsname.h>
  18. #include <limits.h>
  19. #include <sys/param.h>
  20. #include <errno.h>
  21. #ifdef HAVE_CONFIG_H
  22. # include "config.h"
  23. #endif
  24. #if TIME_WITH_SYS_TIME
  25. # include <sys/time.h>
  26. # include <time.h>
  27. #else
  28. # if HAVE_SYS_TIME_H
  29. # include <sys/time.h>
  30. # else
  31. # include <time.h>
  32. # endif
  33. #endif
  34. #include "shared/configfile.h"
  35. #include "shared/sockets.h"
  36. #include "main.h"
  37. #include "mode.h"
  38. #include "machine.h"
  39. #include "chrono.h"
  40. static char *tickTime(char *time, int heartbeat);
  41. /**
  42. * TimeDate Screen displays current time and date, uptime, OS ver...
  43. *
  44. *\verbatim
  45. *
  46. * +--------------------+ +--------------------+
  47. * |## Linux 2.6.11 ###@| |### TIME: myhost ##@|
  48. * |Up xxx days hh:mm:ss| |17.05.2005 11:32:57a|
  49. * | Wed May 17, 1998 | +--------------------+
  50. * |11:32:57a 100% idle|
  51. * +--------------------+
  52. *
  53. *\endverbatim
  54. *
  55. * \param rep Time since last screen update
  56. * \param display 1 if screen is visible or data should be updated
  57. * \param flags_ptr Mode flags
  58. * \return Always 0
  59. */
  60. int
  61. time_screen(int rep, int display, int *flags_ptr)
  62. {
  63. char now[40];
  64. char today[40];
  65. int xoffs;
  66. int days, hour, min, sec;
  67. static int heartbeat = 0;
  68. static const char *timeFormat = NULL;
  69. static const char *dateFormat = NULL;
  70. time_t thetime;
  71. struct tm *rtime;
  72. double uptime, idle;
  73. if ((*flags_ptr & INITIALIZED) == 0) {
  74. *flags_ptr |= INITIALIZED;
  75. /* get config values */
  76. timeFormat = config_get_string("TimeDate", "TimeFormat", 0, "%H:%M:%S");
  77. dateFormat = config_get_string("TimeDate", "DateFormat", 0, "%b %d %Y");
  78. sock_send_string(sock, "screen_add T\n");
  79. sock_printf(sock, "screen_set T -name {Time Screen: %s}\n", get_hostname());
  80. sock_send_string(sock, "widget_add T title title\n");
  81. sock_send_string(sock, "widget_add T one string\n");
  82. if (lcd_hgt >= 4) {
  83. sock_send_string(sock, "widget_add T two string\n");
  84. sock_send_string(sock, "widget_add T three string\n");
  85. // write title bar: OS name, OS version, hostname
  86. sock_printf(sock, "widget_set T title {%s %s: %s}\n",
  87. get_sysname(), get_sysrelease(), get_hostname());
  88. } else {
  89. // write title bar: hostname
  90. sock_printf(sock, "widget_set T title {TIME: %s}\n", get_hostname());
  91. }
  92. }
  93. // toggle colon display
  94. heartbeat ^= 1;
  95. time(&thetime);
  96. rtime = localtime(&thetime);
  97. if (strftime(today, sizeof(today), dateFormat, rtime) == 0)
  98. *today = '\0';
  99. if (strftime(now, sizeof(now), timeFormat, rtime) == 0)
  100. *now = '\0';
  101. tickTime(now, heartbeat);
  102. if (lcd_hgt >= 4) {
  103. char tmp[40]; // should be large enough
  104. machine_get_uptime(&uptime, &idle);
  105. // display the uptime...
  106. days = (int) uptime / 86400;
  107. hour = ((int) uptime % 86400) / 3600;
  108. min = ((int) uptime % 3600) / 60;
  109. sec = ((int) uptime % 60);
  110. if (lcd_wid >= 20)
  111. sprintf(tmp, "Up %3d day%s %02d:%02d:%02d",
  112. days, ((days != 1) ? "s" : ""), hour, min, sec);
  113. else
  114. sprintf(tmp, "Up %dd %02d:%02d:%02d", days, hour, min, sec);
  115. xoffs = (lcd_wid > strlen(tmp)) ? ((lcd_wid - strlen(tmp)) / 2) + 1 : 1;
  116. if (display)
  117. sock_printf(sock, "widget_set T one %i 2 {%s}\n", xoffs, tmp);
  118. // display the date
  119. xoffs = (lcd_wid > strlen(today)) ? ((lcd_wid - strlen(today)) / 2) + 1 : 1;
  120. if (display)
  121. sock_printf(sock, "widget_set T two %i 3 {%s}\n", xoffs, today);
  122. // display the time & idle time...
  123. sprintf(tmp, "%s %3i%% idle", now, (int) idle);
  124. xoffs = (lcd_wid > strlen(tmp)) ? ((lcd_wid - strlen(tmp)) / 2) + 1 : 1;
  125. if (display)
  126. sock_printf(sock, "widget_set T three %i 4 {%s}\n", xoffs, tmp);
  127. }
  128. else { // 2 line version of the screen
  129. xoffs = (lcd_wid > (strlen(today) + strlen(now) + 1))
  130. ? ((lcd_wid - ((strlen(today) + strlen(now) + 1))) / 2) + 1 : 1;
  131. if (display)
  132. sock_printf(sock, "widget_set T one %i 2 {%s %s}\n", xoffs, today, now);
  133. }
  134. return 0;
  135. } // End time_screen()
  136. /**
  137. * OldTime Screen displays current time and date...
  138. *
  139. *\verbatim
  140. *
  141. * +--------------------+ +--------------------+
  142. * |## DATE & TIME ####@| |### TIME: myhost ##@|
  143. * | myhost | |2005-05-17 11:32:57a|
  144. * |11:32:75a Wednesday,| +--------------------+
  145. * | May 17, 2005 |
  146. * +--------------------+
  147. *
  148. *\endverbatim
  149. *
  150. * \param rep Time since last screen update
  151. * \param display 1 if screen is visible or data should be updated
  152. * \param flags_ptr Mode flags
  153. * \return Always 0
  154. */
  155. int
  156. clock_screen(int rep, int display, int *flags_ptr)
  157. {
  158. char now[40];
  159. char today[40];
  160. int xoffs;
  161. static int heartbeat = 0;
  162. static const char *timeFormat = NULL;
  163. static const char *dateFormat = NULL;
  164. time_t thetime;
  165. struct tm *rtime;
  166. if ((*flags_ptr & INITIALIZED) == 0) {
  167. char tmp[257]; // should be large enough for host name
  168. *flags_ptr |= INITIALIZED;
  169. /* get config values */
  170. timeFormat = config_get_string("OldTime", "TimeFormat", 0, "%H:%M:%S");
  171. dateFormat = config_get_string("OldTime", "DateFormat", 0, "%b %d %Y");
  172. sock_send_string(sock, "screen_add O\n");
  173. sock_printf(sock, "screen_set O -name {Old Clock Screen: %s}\n", get_hostname());
  174. sock_send_string(sock, "widget_add O title title\n");
  175. sock_send_string(sock, "widget_add O one string\n");
  176. if (lcd_hgt >= 4) {
  177. sock_send_string(sock, "widget_add O two string\n");
  178. sock_send_string(sock, "widget_add O three string\n");
  179. sock_printf(sock, "widget_set O title {DATE & TIME}\n");
  180. sprintf(tmp, "%s", get_hostname());
  181. xoffs = (lcd_wid > strlen(tmp)) ? (((lcd_wid - strlen(tmp)) / 2) + 1) : 1;
  182. sock_printf(sock, "widget_set O one %i 2 {%s}\n", xoffs, tmp);
  183. } else {
  184. sock_printf(sock, "widget_set O title {TIME: %s}\n", get_hostname());
  185. }
  186. }
  187. // toggle colon display
  188. heartbeat ^= 1;
  189. time(&thetime);
  190. rtime = localtime(&thetime);
  191. if (strftime(today, sizeof(today), dateFormat, rtime) == 0)
  192. *today = '\0';
  193. if (strftime(now, sizeof(now), timeFormat, rtime) == 0)
  194. *now = '\0';
  195. tickTime(now, heartbeat);
  196. if (lcd_hgt >= 4) { // 4-line version of the screen
  197. xoffs = (lcd_wid > strlen(today)) ? ((lcd_wid - strlen(today)) / 2) + 1 : 1;
  198. if (display)
  199. sock_printf(sock, "widget_set O two %i 3 {%s}\n", xoffs, today);
  200. xoffs = (lcd_wid > strlen(now)) ? ((lcd_wid - strlen(now)) / 2) + 1 : 1;
  201. if (display)
  202. sock_printf(sock, "widget_set O three %i 4 {%s}\n", xoffs, now);
  203. }
  204. else { // 2-line version of the screen
  205. xoffs = (lcd_wid > (strlen(today) + strlen(now) + 1))
  206. ? ((lcd_wid - ((strlen(today) + strlen(now) + 1))) / 2) + 1 : 1;
  207. if (display)
  208. sock_printf(sock, "widget_set O one %i 2 {%s %s}\n", xoffs, today, now);
  209. }
  210. return 0;
  211. } // End clock_screen()
  212. /**
  213. * Uptime Screen shows info about system uptime and OS version
  214. *
  215. *\verbatim
  216. *
  217. * +--------------------+ +--------------------+
  218. * |## SYSTEM UPTIME ##@| |# Linux 2.6.11: my#@|
  219. * | myhost | | xxx days hh:mm:ss |
  220. * | xxx days hh:mm:ss | +--------------------+
  221. * | Linux 2.6.11 |
  222. * +--------------------+
  223. *
  224. *\endverbatim
  225. *
  226. * \param rep Time since last screen update
  227. * \param display 1 if screen is visible or data should be updated
  228. * \param flags_ptr Mode flags
  229. * \return Always 0
  230. */
  231. int
  232. uptime_screen(int rep, int display, int *flags_ptr)
  233. {
  234. int xoffs;
  235. int days, hour, min, sec;
  236. double uptime, idle;
  237. static int heartbeat = 0;
  238. char tmp[257]; // should be large enough for host name
  239. if ((*flags_ptr & INITIALIZED) == 0) {
  240. *flags_ptr |= INITIALIZED;
  241. sock_send_string(sock, "screen_add U\n");
  242. sock_printf(sock, "screen_set U -name {Uptime Screen: %s}\n", get_hostname());
  243. sock_send_string(sock, "widget_add U title title\n");
  244. if (lcd_hgt >= 4) {
  245. sock_send_string(sock, "widget_add U one string\n");
  246. sock_send_string(sock, "widget_add U two string\n");
  247. sock_send_string(sock, "widget_add U three string\n");
  248. sock_send_string(sock, "widget_set U title {SYSTEM UPTIME}\n");
  249. sprintf(tmp, "%s", get_hostname());
  250. xoffs = (lcd_wid > strlen(tmp)) ? (((lcd_wid - strlen(tmp)) / 2) + 1) : 1;
  251. sock_printf(sock, "widget_set U one %i 2 {%s}\n", xoffs, tmp);
  252. sprintf(tmp, "%s %s", get_sysname(), get_sysrelease());
  253. xoffs = (lcd_wid > strlen(tmp)) ? (((lcd_wid - strlen(tmp)) / 2) + 1) : 1;
  254. sock_printf(sock, "widget_set U three %i 4 {%s}\n", xoffs, tmp);
  255. } else {
  256. sock_send_string(sock, "widget_add U one string\n");
  257. sock_printf(sock, "widget_set U title {%s %s: %s}\n",
  258. get_sysname(), get_sysrelease(), get_hostname());
  259. }
  260. }
  261. // toggle colon display
  262. heartbeat ^= 1;
  263. machine_get_uptime(&uptime, &idle);
  264. days = (int) uptime / 86400;
  265. hour = ((int) uptime % 86400) / 3600;
  266. min = ((int) uptime % 3600) / 60;
  267. sec = ((int) uptime % 60);
  268. if (lcd_wid >= 20)
  269. sprintf(tmp, "%d day%s %02d:%02d:%02d",
  270. days, ((days != 1) ? "s" : ""), hour, min, sec);
  271. else
  272. sprintf(tmp, "%dd %02d:%02d:%02d", days, hour, min, sec);
  273. if (display) {
  274. xoffs = (lcd_wid > strlen(tmp)) ? (((lcd_wid - strlen(tmp)) / 2) + 1) : 1;
  275. if (lcd_hgt >= 4)
  276. sock_printf(sock, "widget_set U two %d 3 {%s}\n", xoffs, tmp);
  277. else
  278. sock_printf(sock, "widget_set U one %d 2 {%s}\n", xoffs, tmp);
  279. }
  280. return 0;
  281. } // End uptime_screen()
  282. /**
  283. * Big Clock Screen displays current time...
  284. *
  285. *\verbatim
  286. *
  287. * +--------------------+
  288. * | _ _ _ _ |
  289. * | ||_ . _||_|. _| ||
  290. * | ||_|. _| |.|_ ||
  291. * | |
  292. * +--------------------+
  293. *
  294. *\endverbatim
  295. *
  296. * \param rep Time since last screen update
  297. * \param display 1 if screen is visible or data should be updated
  298. * \param flags_ptr Mode flags
  299. * \return Always 0
  300. */
  301. int
  302. big_clock_screen(int rep, int display, int *flags_ptr)
  303. {
  304. time_t thetime;
  305. struct tm *rtime;
  306. int pos[] = { 1, 4, 8, 11, 15, 18 };
  307. char fulltxt[16];
  308. static char old_fulltxt[16];
  309. static int heartbeat = 0;
  310. static int TwentyFourHour = 1;
  311. int j = 0;
  312. int digits = (lcd_wid >= 20) ? 6 : 4;
  313. int xoffs = (lcd_wid + 1 - (pos[digits-1] + 2)) / 2;
  314. // toggle colon display
  315. heartbeat ^= 1;
  316. if ((*flags_ptr & INITIALIZED) == 0) {
  317. *flags_ptr |= INITIALIZED;
  318. sock_send_string(sock, "screen_add K\n");
  319. sock_send_string(sock, "screen_set K -name {Big Clock Screen} -heartbeat off\n");
  320. sock_send_string(sock, "widget_add K d0 num\n");
  321. sock_send_string(sock, "widget_add K d1 num\n");
  322. sock_send_string(sock, "widget_add K d2 num\n");
  323. sock_send_string(sock, "widget_add K d3 num\n");
  324. sock_send_string(sock, "widget_add K c0 num\n");
  325. if (digits > 4) {
  326. sock_send_string(sock, "widget_add K d4 num\n");
  327. sock_send_string(sock, "widget_add K d5 num\n");
  328. sock_send_string(sock, "widget_add K c1 num\n");
  329. }
  330. strcpy(old_fulltxt, " ");
  331. }
  332. time(&thetime);
  333. rtime = localtime(&thetime);
  334. sprintf(fulltxt, "%02d%02d%02d",
  335. ((TwentyFourHour) ? rtime->tm_hour : (((rtime->tm_hour + 11) % 12) + 1)),
  336. rtime->tm_min, rtime->tm_sec);
  337. for (j = 0; j < digits; j++) {
  338. if (fulltxt[j] != old_fulltxt[j]) {
  339. sock_printf(sock, "widget_set K d%d %d %c\n", j, xoffs+pos[j], fulltxt[j]);
  340. old_fulltxt[j] = fulltxt[j];
  341. }
  342. }
  343. if (heartbeat) { // 10 means: colon
  344. sock_printf(sock, "widget_set K c0 %d 10\n", xoffs + 7);
  345. if (digits > 4)
  346. sock_printf(sock, "widget_set K c1 %d 10\n", xoffs + 14);
  347. }
  348. else { // kludge: use illegal number to clear colon display
  349. sock_printf(sock, "widget_set K c0 %d 11\n", xoffs + 7);
  350. if (digits > 4)
  351. sock_printf(sock, "widget_set K c1 %d 11\n", xoffs + 14);
  352. }
  353. return 0;
  354. } // End big_clock_screen()
  355. /**
  356. * MiniClock Screen displays the current time with hours & minutes only
  357. *
  358. *\verbatim
  359. *
  360. * +--------------------+ +--------------------+
  361. * | | | 11:32 |
  362. * | 11:32 | | |
  363. * | | +--------------------+
  364. * | |
  365. * +--------------------+
  366. *
  367. *\endverbatim
  368. *
  369. * \param rep Time since last screen update
  370. * \param display 1 if screen is visible or data should be updated
  371. * \param flags_ptr Mode flags
  372. * \return Always 0
  373. */
  374. int
  375. mini_clock_screen(int rep, int display, int *flags_ptr)
  376. {
  377. char now[40];
  378. time_t thetime;
  379. struct tm *rtime;
  380. static const char *timeFormat = NULL;
  381. static int heartbeat = 0;
  382. int xoffs;
  383. // toggle colon display
  384. heartbeat ^= 1;
  385. if ((*flags_ptr & INITIALIZED) == 0) {
  386. *flags_ptr |= INITIALIZED;
  387. /* get config values */
  388. timeFormat = config_get_string("MiniClock", "TimeFormat", 0, "%H:%M");
  389. sock_send_string(sock, "screen_add N\n");
  390. sock_send_string(sock, "screen_set N -name {Mini Clock Screen} -heartbeat off\n");
  391. sock_send_string(sock, "widget_add N one string\n");
  392. }
  393. time(&thetime);
  394. rtime = localtime(&thetime);
  395. if (strftime(now, sizeof(now), timeFormat, rtime) == 0)
  396. *now = '\0';
  397. tickTime(now, heartbeat);
  398. xoffs = (lcd_wid > strlen(now)) ? (((lcd_wid - strlen(now)) / 2) + 1) : 1;
  399. sock_printf(sock, "widget_set N one %d %d {%s}\n", xoffs, (lcd_hgt / 2), now);
  400. return 0;
  401. } // End mini_clock_screen()
  402. /** Helper function: toggle between ':' and ' ' in time strings.
  403. * \note The time string passed is modified directly!
  404. * \param time String containing a formatted time value.
  405. * \param heartbeat Even numbers to display ':', odd to display ' '.
  406. * \return Pointer to the modfied time string.
  407. */
  408. static char *
  409. tickTime(char *time, int heartbeat)
  410. {
  411. if (time != NULL) {
  412. static char colon[] = {':', ' '};
  413. char *ptr = time;
  414. for (heartbeat %= 2; *ptr != '\0'; ptr++) {
  415. if (*ptr == colon[0])
  416. *ptr = colon[heartbeat];
  417. }
  418. }
  419. return(time);
  420. }