Code

Added an optional clock screen :)
[ncmpc.git] / src / screen_clock.c
1 /*
2  * This file is based on the 'Grand digital clock' (gdc.c) shipped with 
3  * ncurses. 
4  */
6 #include <time.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <glib.h>
10 #include <ncurses.h>
12 #include "config.h"
14 #ifdef  ENABLE_CLOCK_SCREEN
15 #include "ncmpc.h"
16 #include "libmpdclient.h"
17 #include "options.h"
18 #include "mpc.h"
19 #include "command.h"
20 #include "screen.h"
21 #include "screen_utils.h"
23 #define YDEPTH  5
24 #define BUFSIZE 64
26 #define ENABLE_SECONDS 0
28 static window_t win = { NULL, 0, 0 };
29 static gboolean enable_seconds = ENABLE_SECONDS;
31 /* orginal variables from gdc.c */
32 static short disp[11] =
33 {
34     075557, 011111, 071747, 071717, 055711,
35     074717, 074757, 071111, 075757, 075717, 002020
36 };
38 static long older[6], next[6], newer[6], mask;
40 static int YBASE = 10;
41 static int XBASE = 10;
42 static int XLENGTH = 54;
44 /* orginal functions */
45 static void
46 set(int t, int n)
47 {
48   int i, m;
50   m = 7 << n;
51   for (i = 0; i < 5; i++) {
52     next[i] |= ((disp[t] >> ((4 - i) * 3)) & 07) << n;
53     mask |= (next[i] ^ older[i]) & m;
54   }
55   if (mask & m)
56     mask |= m;
57 }
59 static void
60 drawbox(void)
61 {
62   chtype bottom[XLENGTH + 1];
63   int n;
65   mvwaddch(win.w, YBASE - 1, XBASE - 1, ACS_ULCORNER);
66   whline(win.w, ACS_HLINE, XLENGTH);
67   mvwaddch(win.w, YBASE - 1, XBASE + XLENGTH, ACS_URCORNER);
69   mvwaddch(win.w, YBASE + YDEPTH, XBASE - 1, ACS_LLCORNER);
70   mvwinchnstr(win.w, YBASE + YDEPTH, XBASE, bottom, XLENGTH);
71   for (n = 0; n < XLENGTH; n++)
72     bottom[n] = ACS_HLINE | (bottom[n] & (A_ATTRIBUTES | A_COLOR));
73   mvwaddchnstr(win.w, YBASE + YDEPTH, XBASE, bottom, XLENGTH);
74   mvwaddch(win.w, YBASE + YDEPTH, XBASE + XLENGTH, ACS_LRCORNER);
75   
76   wmove(win.w, YBASE, XBASE - 1);
77   wvline(win.w, ACS_VLINE, YDEPTH);
78   
79   wmove(win.w, YBASE, XBASE + XLENGTH);
80   wvline(win.w, ACS_VLINE, YDEPTH);
81 }
84 static void
85 standt(int on)
86 {
87   if(on)
88     wattron(win.w, A_REVERSE);
89   else
90     wattroff(win.w, A_REVERSE);
91 }
95 /* ncmpc screen functions */
97 static void
98 clock_resize(int cols, int rows)
99 {
100   int j;
101   
102   for (j = 0; j < 5; j++)
103     older[j] = newer[j] = next[j] = 0;
105   win.cols = cols;
106   win.rows = rows;
107   
108   if( cols<60 )
109     enable_seconds = FALSE;
110   else
111     enable_seconds = ENABLE_SECONDS;
113   if( enable_seconds )
114     XLENGTH = 54;
115   else
116     XLENGTH = 54-18;
118   
119   XBASE = (cols-XLENGTH)/2;
120   YBASE = (rows-YDEPTH)/2-(YDEPTH/2);
123 static void 
124 clock_init(WINDOW *w, int cols, int rows)
126   win.w = w;
127   clock_resize(cols, rows);
130 static void 
131 clock_exit(void)
135 static void 
136 clock_open(screen_t *screen, mpd_client_t *c)
138   int j;
140   for (j = 0; j < 5; j++)
141     older[j] = newer[j] = next[j] = 0;
145 static void 
146 clock_close(void)
150 static char *
151 clock_title(void)
153   return _("Music Player Client - Clock");
156 static void 
157 clock_update(screen_t *screen, mpd_client_t *c)
158 {  
159   time_t now;
160   struct tm *tm;
161   long t, a;
162   int i, j, s, k;
163   char buf[BUFSIZE];
164   
165   time(&now);
166   tm = localtime(&now);
167   
168   mask = 0;
169   set(tm->tm_sec % 10, 0);
170   set(tm->tm_sec / 10, 4);
171   set(tm->tm_min % 10, 10);
172   set(tm->tm_min / 10, 14);
173   set(tm->tm_hour % 10, 20);
174   set(tm->tm_hour / 10, 24);
175   set(10, 7);
176   set(10, 17);
178   for (k = 0; k < 6; k++) {
179     newer[k] = (newer[k] & ~mask) | (next[k] & mask);
180     next[k] = 0;
181     for (s = 1; s >= 0; s--) {
182       standt(s);
183       for (i = 0; i < 6; i++) {
184         if ((a = (newer[i] ^ older[i]) & (s ? newer : older)[i])
185             != 0) {
186           for (j = 0, t = 1 << 26; t; t >>= 1, j++) {
187             if (a & t) {
188               if (!(a & (t << 1))) {
189                 wmove(win.w, YBASE + i, XBASE + 2 * j);
190               }
191               if( enable_seconds || j<18 )
192                 waddstr(win.w, "  ");
193             }
194           }
195         }
196         if (!s) {
197           older[i] = newer[i];
198         }
199       }
200       if (!s) {
201         wrefresh(win.w);
202       }
203     }
204   }
205   
206 #ifdef HAVE_LOCALE_H
207   strftime(buf, BUFSIZE, "%x", tm);
208 # else
209   /* this depends on the detailed format of ctime(3) */
210   strcpy(buf, ctime(&now));
211   strcpy(buf + 10, buf + 19);
212 #endif
213   mvwaddstr(win.w, YBASE+YDEPTH+1, (win.cols-strlen(buf))/2, buf);
214   
215   wmove(win.w, 6, 0);
216   drawbox();
217   wrefresh(win.w);
220 static void 
221 clock_paint(screen_t *screen, mpd_client_t *c)
223   /* this seems to be a better way to clear the window than wclear() ?! */
224   wmove(win.w, 0, 0);
225   wclrtobot(win.w);
226   clock_update(screen, c);
231 static int 
232 clock_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
234   return 0;
238 screen_functions_t *
239 get_screen_clock(void)
241   static screen_functions_t functions;
243   memset(&functions, 0, sizeof(screen_functions_t));
244   functions.init   = clock_init;
245   functions.exit   = clock_exit;
246   functions.open   = clock_open;
247   functions.close  = clock_close;
248   functions.resize = clock_resize;
249   functions.paint  = clock_paint;
250   functions.update = clock_update;
251   functions.cmd    = clock_cmd;
252   functions.get_lw = NULL;
253   functions.get_title = clock_title;
255   return &functions;
259 #endif