From 1fddc966d25022ba3e198ab7100e500c4ce1450d Mon Sep 17 00:00:00 2001 From: David Phillips Date: Sat, 2 Mar 2019 23:25:29 +1300 Subject: Rename from test to clock-disp --- .gitignore | 2 +- Makefile | 2 +- clock-disp.c | 397 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test.c | 397 ----------------------------------------------------------- 4 files changed, 399 insertions(+), 399 deletions(-) create mode 100644 clock-disp.c delete mode 100644 test.c diff --git a/.gitignore b/.gitignore index 9daeafb..eb35041 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -test +clock-disp diff --git a/Makefile b/Makefile index 328ae10..231df95 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ include config.mk -all: test +all: clock-disp diff --git a/clock-disp.c b/clock-disp.c new file mode 100644 index 0000000..c8d8c74 --- /dev/null +++ b/clock-disp.c @@ -0,0 +1,397 @@ +#include +#include +#include +#include +#include +#include +#include + +enum ALIGN_MODE { + ALIGN_MODE_LEFT, + ALIGN_MODE_CENTRE, + ALIGN_MODE_RIGHT, +}; + +#define WINDOW_TITLE "Clock Display" +#define SCREEN_WIDTH 800 +#define SCREEN_HEIGHT 480 + +#define TIME_X 0 +#define TIME_Y -50 + +#define NO_LOCK_Y 150 + +#define DATE_1_X 20 +#define DATE_1_Y 295 +#define DATE_2_X 20 +#define DATE_2_Y 350 + +#define SECONDS_X SCREEN_WIDTH - 80 +#define SECONDS_Y SCREEN_HEIGHT - 55 + +#define NTP_INFO_X 240 +#define NTP_INFO_Y SCREEN_HEIGHT - 55 +#define SAT_INFO_X 20 +#define SAT_INFO_Y NTP_INFO_Y + +#define SUN_INFO_X SCREEN_WIDTH -20 +#define SUN_INFO_1_Y DATE_1_Y +#define SUN_INFO_2_Y DATE_2_Y + +/* Common colours used */ +#define COLOUR_WHITE ((SDL_Color){255,255,255,255}) +#define COLOUR_YELLOW ((SDL_Color){255,191, 32,255}) +#define COLOUR_40GRAY ((SDL_Color){100,100,100,255}) + +static sem_t data_lock; +struct clock_data { + int is_unread; + char sunrise_time[8]; + char sunset_time[8]; + int sat_seen; + int sat_used; + int leap_second; + int offset; + char offset_units[8]; + int no_gps_lock; +}; + +static volatile struct clock_data shared_data; + +/** + * Publish a struct clock_data to the volatile global clock data object. + * Caller MUST already hold data_lock + */ +void publish_clock_data(struct clock_data *l) +{ + char *d = (char*)&shared_data; + char *s = (char*)l; + size_t i = 0; + for (i = 0; i < sizeof(struct clock_data); i++) { + d[i] = s[i]; + } + shared_data.is_unread = 1; +} + +/** + * Copy the published struct clock_data to a non-volatile clock data object. + * Caller MUST already hold data_lock + */ +void get_clock_data(struct clock_data *l) +{ + char *d = (char*)l; + char *s = (char*)&shared_data; + size_t i = 0; + for (i = 0; i < sizeof(struct clock_data); i++) { + d[i] = s[i]; + } +} + +/** + * Read clock's statistics from files and push them into shared data area for + * display thread to pick up + */ +void *read_stats(void* unused) +{ + char buffer[32]; + char *next = buffer; + FILE *f = NULL; + struct clock_data l; + memset(&l, 0, sizeof(l)); + + while (1) { + /* Read sunrise, sunset */ + if (f = fopen("/tmp/stats-sun", "r")) { + if (fgets(buffer, sizeof(buffer), f)) { + /* format is %d/%d\n, first is used sats, second is total seen */ + if (next = strchr(buffer, ',')) { + *(next++) = '\0'; + next[strcspn(next, "\n\r\t")] = '\0'; + strncpy(l.sunrise_time, buffer, sizeof(l.sunrise_time)); + strncpy(l.sunset_time, next, sizeof(l.sunset_time)); + } + } + fclose(f); + } + + /* Read satellite stats */ + if (f = fopen("/tmp/stats-sats", "r")) { + if (fgets(buffer, sizeof(buffer), f)) { + /* format is %d,%d\n, first is used sats, second is total seen */ + if (next = strchr(buffer, '/')) { + *(next++) = '\0'; + l.sat_used = strtod(buffer, NULL); + l.sat_seen = strtod(next, NULL); + } + } + fclose(f); + } + + /* read leap second status file - also helps determine lock */ + if (f = fopen("/tmp/stats-leap", "r")) { + if (fgets(buffer, sizeof(buffer), f)) { + buffer[strcspn(buffer, "\n\r\t")] = '\0'; + l.no_gps_lock = !strcmp(buffer, "Not synchronised"); + l.leap_second = strcmp(buffer, "Normal"); + } + fclose(f); + } + + if (f = fopen("/tmp/stats-clock", "r")) { + if (fgets(buffer, sizeof(buffer), f)) { + const char *units[] = { "s", "ms", "µs", "ns", "ps", "fs" }; + int i = 0; + double offset = fabs(strtod(buffer, NULL)); + while (offset < 1 && i < sizeof(units)/sizeof(units[0]) - 1) { + i++; + offset *= 1000; + } + l.offset = offset; + strncpy(l.offset_units, units[i], sizeof(l.offset_units)); + } + fclose(f); + } + sem_wait(&data_lock); + publish_clock_data(&l); + sem_post(&data_lock); + sleep(5); + } +} + +const char *get_th_suffix(unsigned int day) +{ + if (11 <= day && day <= 19) { + return "th"; + } else { + switch (day % 10) { + case 1: return "st"; + case 2: return "nd"; + case 3: return "rd"; + default: /* 0, 4-9 */ + return "th"; + } + } +} + +TTF_Font *loadFont(const char *file, int size) +{ + TTF_Font *font = TTF_OpenFont(file, size); + if (!font) { + printf("Error: TTF_OpenFont: %s\n", TTF_GetError()); + return NULL; + } + return font; +} + +void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y){ + //Setup the destination rectangle to be at the position we want + SDL_Rect dst; + dst.x = x; + dst.y = y; + //Query the texture to get its width and height to use + SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h); + SDL_RenderCopy(ren, tex, NULL, &dst); +} + + +SDL_Texture* renderText(const char *message, TTF_Font *font, SDL_Color color, SDL_Renderer *renderer) +{ + //We need to first render to a surface as that's what TTF_RenderText + //returns, then load that surface into a texture + SDL_Surface *surf = TTF_RenderUTF8_Blended(font, message, color); + if (!surf){ + printf("Error in TTF_RenderUTF8_Blended\n"); + return NULL; + } + SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surf); + if (!texture){ + printf("Error in SDL_CreateTextureFromSurface\n"); + } + //Clean up the surface and font + SDL_FreeSurface(surf); + return texture; +} + +int drawText(const char *text, TTF_Font *font, SDL_Color color, SDL_Renderer *renderer, int x, int y, enum ALIGN_MODE mode) { + /* FIXME does this need better error detection */ + int text_w; + SDL_Texture *image; + image = renderText(text, font, color, renderer); + SDL_QueryTexture(image, NULL, NULL, &text_w, NULL); + + if (mode == ALIGN_MODE_CENTRE) { + x = SCREEN_WIDTH / 2 - text_w / 2; + } else if (mode == ALIGN_MODE_RIGHT) { + x -= text_w; + } + renderTexture(image, renderer, x, y); + SDL_DestroyTexture(image); + return x + (mode == ALIGN_MODE_RIGHT? 0 : 1) * text_w; +} + +int main(void) +{ + struct clock_data l; + + /* initial unread indicator value */ + shared_data.is_unread = 0; + + strncpy(l.sunrise_time, "??:??", sizeof(l.sunrise_time)); + strncpy(l.sunset_time, "??:??", sizeof(l.sunset_time)); + l.sat_seen = 0; + l.sat_used = 0; + l.leap_second = 0; + l.offset = 0; + strncpy(l.offset_units, "?", sizeof(l.offset_units)); + l.no_gps_lock = 1; + + if (sem_init(&data_lock, 0, 1)) { + perror("sem_init"); + return 1; + } + + int stop = 0; + SDL_Event e; + SDL_Window *window; + + SDL_Init(SDL_INIT_VIDEO); + TTF_Init(); + + TTF_Font *mainTimeFont = loadFont("/usr/share/fonts/TTF/RobotoMono-Regular.ttf", 325); + TTF_Font *noLockFont = loadFont("/usr/share/fonts/TTF/Roboto-Regular.ttf", 130); + TTF_Font *secondsFont = loadFont("/usr/share/fonts/TTF/RobotoMono-Regular.ttf", 30); + + TTF_Font *dateFont = loadFont("/usr/share/fonts/TTF/Roboto-Regular.ttf", 50); + TTF_Font *dateSymbolFont = loadFont("/usr/share/fonts/TTF/Symbola.ttf", 50); + + TTF_Font *ntpInfoFont= loadFont("/usr/share/fonts/TTF/Roboto-Regular.ttf", 30); + TTF_Font *ntpSymbolFont = loadFont("/usr/share/fonts/TTF/Symbola.ttf", 30); + if ( !ntpSymbolFont + || !dateSymbolFont + || !mainTimeFont + || !dateFont + || !secondsFont + || !ntpInfoFont) { + return 1; + } + + /* launch pthread */ + pthread_t thread; + if (pthread_create(&thread, NULL, read_stats, NULL) != 0) { + perror("pthread_create"); + return 1; + } + + window = SDL_CreateWindow(WINDOW_TITLE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL); + if (!window) { + printf("Could not create window: %s\n", SDL_GetError()); + return 1; + } + + SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (!renderer) { + SDL_DestroyWindow(window); + printf("SDL_CreateRenderer Error\n"); + SDL_Quit(); + return 1; + } + + while (!stop) + { + while (SDL_PollEvent(&e)){ + if ( e.type == SDL_QUIT + || e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_q) { + stop = 1; + } + } + char text[64]; + time_t t; + struct tm *time_s; + + + SDL_Texture *image; + int text_w; + + SDL_RenderClear(renderer); + + t = time(NULL); + if ((time_s = localtime(&t)) == NULL) { + /* FIXME error */ + continue; + } + + int next_x = 0; + + sem_wait(&data_lock); + if (shared_data.is_unread) { + get_clock_data(&l); + shared_data.is_unread = 0; + } + sem_post(&data_lock); + + if (l.sat_seen == 0 || l.sat_used == 0 || l.no_gps_lock) { + drawText("No GPS Lock", noLockFont, COLOUR_WHITE, renderer, 0, NO_LOCK_Y, ALIGN_MODE_CENTRE); + } else { + /* Have GPS lock, go for it */ + /**/ + strftime(text, sizeof(text), "%H%M", time_s); + drawText(text, mainTimeFont, COLOUR_WHITE, renderer, TIME_X, TIME_Y, ALIGN_MODE_CENTRE); + /**/ + + /********************/ + /* Draws a date string, normally like: + * Monday the 25th + * February, 2019 + */ + strftime(text, sizeof(text), "%A", time_s); + next_x = drawText(text, dateFont, COLOUR_WHITE, renderer, DATE_1_X, DATE_1_Y, ALIGN_MODE_LEFT); + + next_x = drawText(" the ", dateFont, COLOUR_40GRAY, renderer, next_x, DATE_1_Y, ALIGN_MODE_LEFT); + + snprintf(text, sizeof(text), "%d%s", time_s->tm_mday, get_th_suffix(time_s->tm_mday)); + next_x = drawText(text, dateFont, COLOUR_WHITE, renderer, next_x, DATE_1_Y, ALIGN_MODE_LEFT); + next_x = drawText(".", dateFont, COLOUR_40GRAY, renderer, next_x, DATE_1_Y, ALIGN_MODE_LEFT); + + strftime(text, sizeof(text), "%B", time_s); + next_x = drawText(text, dateFont, COLOUR_WHITE, renderer, DATE_2_X, DATE_2_Y, ALIGN_MODE_LEFT); + + next_x = drawText(", ", dateFont, COLOUR_40GRAY, renderer, next_x, DATE_2_Y, ALIGN_MODE_LEFT); + + strftime(text, sizeof(text), "%Y", time_s); + next_x = drawText(text, dateFont, COLOUR_WHITE, renderer, next_x, DATE_2_Y, ALIGN_MODE_LEFT); + /********************/ + + /**/ + strftime(text, sizeof(text), ":%S", time_s); + next_x = drawText(text, secondsFont, COLOUR_WHITE, renderer, SECONDS_X, SECONDS_Y, ALIGN_MODE_LEFT); + /**/ + + /**/ + next_x = drawText("⏰ ", ntpSymbolFont, COLOUR_40GRAY, renderer, NTP_INFO_X, NTP_INFO_Y, ALIGN_MODE_LEFT); + snprintf(text, sizeof(text), " RMS %d %s%s ", l.offset, l.offset_units, + l.leap_second ? ", Leap second coming!" : ""); + next_x = drawText(text, ntpInfoFont, COLOUR_40GRAY, renderer, next_x, NTP_INFO_Y, ALIGN_MODE_LEFT); + /**/ + + /**/ + next_x = drawText(l.sunrise_time, dateFont, COLOUR_WHITE, renderer, SUN_INFO_X, SUN_INFO_1_Y, ALIGN_MODE_RIGHT); + next_x = drawText("☀⬆", dateSymbolFont, COLOUR_YELLOW, renderer, next_x, SUN_INFO_1_Y, ALIGN_MODE_RIGHT); + next_x = drawText(l.sunset_time, dateFont, COLOUR_WHITE, renderer, SUN_INFO_X, SUN_INFO_2_Y, ALIGN_MODE_RIGHT); + next_x = drawText("☀⬇", dateSymbolFont, COLOUR_YELLOW, renderer, next_x, SUN_INFO_2_Y, ALIGN_MODE_RIGHT); + // next_x = drawText("⭡05:45 ↓20:13", dateFont, COLOUR_WHITE, renderer, SUN_INFO_X, SUN_INFO_Y); + /**/ + } + /**/ + next_x = drawText("🛰 ", ntpSymbolFont, COLOUR_40GRAY, renderer, SAT_INFO_X, SAT_INFO_Y, ALIGN_MODE_LEFT); + snprintf(text, sizeof(text), "%d (%d used)", l.sat_seen, l.sat_used); + next_x = drawText(text, ntpInfoFont, COLOUR_40GRAY, renderer, next_x, NTP_INFO_Y, ALIGN_MODE_LEFT); + /**/ + SDL_RenderPresent(renderer); + SDL_Delay(100); + } + + SDL_DestroyWindow(window); + SDL_Quit(); + return 0; +} + diff --git a/test.c b/test.c deleted file mode 100644 index c8d8c74..0000000 --- a/test.c +++ /dev/null @@ -1,397 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -enum ALIGN_MODE { - ALIGN_MODE_LEFT, - ALIGN_MODE_CENTRE, - ALIGN_MODE_RIGHT, -}; - -#define WINDOW_TITLE "Clock Display" -#define SCREEN_WIDTH 800 -#define SCREEN_HEIGHT 480 - -#define TIME_X 0 -#define TIME_Y -50 - -#define NO_LOCK_Y 150 - -#define DATE_1_X 20 -#define DATE_1_Y 295 -#define DATE_2_X 20 -#define DATE_2_Y 350 - -#define SECONDS_X SCREEN_WIDTH - 80 -#define SECONDS_Y SCREEN_HEIGHT - 55 - -#define NTP_INFO_X 240 -#define NTP_INFO_Y SCREEN_HEIGHT - 55 -#define SAT_INFO_X 20 -#define SAT_INFO_Y NTP_INFO_Y - -#define SUN_INFO_X SCREEN_WIDTH -20 -#define SUN_INFO_1_Y DATE_1_Y -#define SUN_INFO_2_Y DATE_2_Y - -/* Common colours used */ -#define COLOUR_WHITE ((SDL_Color){255,255,255,255}) -#define COLOUR_YELLOW ((SDL_Color){255,191, 32,255}) -#define COLOUR_40GRAY ((SDL_Color){100,100,100,255}) - -static sem_t data_lock; -struct clock_data { - int is_unread; - char sunrise_time[8]; - char sunset_time[8]; - int sat_seen; - int sat_used; - int leap_second; - int offset; - char offset_units[8]; - int no_gps_lock; -}; - -static volatile struct clock_data shared_data; - -/** - * Publish a struct clock_data to the volatile global clock data object. - * Caller MUST already hold data_lock - */ -void publish_clock_data(struct clock_data *l) -{ - char *d = (char*)&shared_data; - char *s = (char*)l; - size_t i = 0; - for (i = 0; i < sizeof(struct clock_data); i++) { - d[i] = s[i]; - } - shared_data.is_unread = 1; -} - -/** - * Copy the published struct clock_data to a non-volatile clock data object. - * Caller MUST already hold data_lock - */ -void get_clock_data(struct clock_data *l) -{ - char *d = (char*)l; - char *s = (char*)&shared_data; - size_t i = 0; - for (i = 0; i < sizeof(struct clock_data); i++) { - d[i] = s[i]; - } -} - -/** - * Read clock's statistics from files and push them into shared data area for - * display thread to pick up - */ -void *read_stats(void* unused) -{ - char buffer[32]; - char *next = buffer; - FILE *f = NULL; - struct clock_data l; - memset(&l, 0, sizeof(l)); - - while (1) { - /* Read sunrise, sunset */ - if (f = fopen("/tmp/stats-sun", "r")) { - if (fgets(buffer, sizeof(buffer), f)) { - /* format is %d/%d\n, first is used sats, second is total seen */ - if (next = strchr(buffer, ',')) { - *(next++) = '\0'; - next[strcspn(next, "\n\r\t")] = '\0'; - strncpy(l.sunrise_time, buffer, sizeof(l.sunrise_time)); - strncpy(l.sunset_time, next, sizeof(l.sunset_time)); - } - } - fclose(f); - } - - /* Read satellite stats */ - if (f = fopen("/tmp/stats-sats", "r")) { - if (fgets(buffer, sizeof(buffer), f)) { - /* format is %d,%d\n, first is used sats, second is total seen */ - if (next = strchr(buffer, '/')) { - *(next++) = '\0'; - l.sat_used = strtod(buffer, NULL); - l.sat_seen = strtod(next, NULL); - } - } - fclose(f); - } - - /* read leap second status file - also helps determine lock */ - if (f = fopen("/tmp/stats-leap", "r")) { - if (fgets(buffer, sizeof(buffer), f)) { - buffer[strcspn(buffer, "\n\r\t")] = '\0'; - l.no_gps_lock = !strcmp(buffer, "Not synchronised"); - l.leap_second = strcmp(buffer, "Normal"); - } - fclose(f); - } - - if (f = fopen("/tmp/stats-clock", "r")) { - if (fgets(buffer, sizeof(buffer), f)) { - const char *units[] = { "s", "ms", "µs", "ns", "ps", "fs" }; - int i = 0; - double offset = fabs(strtod(buffer, NULL)); - while (offset < 1 && i < sizeof(units)/sizeof(units[0]) - 1) { - i++; - offset *= 1000; - } - l.offset = offset; - strncpy(l.offset_units, units[i], sizeof(l.offset_units)); - } - fclose(f); - } - sem_wait(&data_lock); - publish_clock_data(&l); - sem_post(&data_lock); - sleep(5); - } -} - -const char *get_th_suffix(unsigned int day) -{ - if (11 <= day && day <= 19) { - return "th"; - } else { - switch (day % 10) { - case 1: return "st"; - case 2: return "nd"; - case 3: return "rd"; - default: /* 0, 4-9 */ - return "th"; - } - } -} - -TTF_Font *loadFont(const char *file, int size) -{ - TTF_Font *font = TTF_OpenFont(file, size); - if (!font) { - printf("Error: TTF_OpenFont: %s\n", TTF_GetError()); - return NULL; - } - return font; -} - -void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y){ - //Setup the destination rectangle to be at the position we want - SDL_Rect dst; - dst.x = x; - dst.y = y; - //Query the texture to get its width and height to use - SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h); - SDL_RenderCopy(ren, tex, NULL, &dst); -} - - -SDL_Texture* renderText(const char *message, TTF_Font *font, SDL_Color color, SDL_Renderer *renderer) -{ - //We need to first render to a surface as that's what TTF_RenderText - //returns, then load that surface into a texture - SDL_Surface *surf = TTF_RenderUTF8_Blended(font, message, color); - if (!surf){ - printf("Error in TTF_RenderUTF8_Blended\n"); - return NULL; - } - SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surf); - if (!texture){ - printf("Error in SDL_CreateTextureFromSurface\n"); - } - //Clean up the surface and font - SDL_FreeSurface(surf); - return texture; -} - -int drawText(const char *text, TTF_Font *font, SDL_Color color, SDL_Renderer *renderer, int x, int y, enum ALIGN_MODE mode) { - /* FIXME does this need better error detection */ - int text_w; - SDL_Texture *image; - image = renderText(text, font, color, renderer); - SDL_QueryTexture(image, NULL, NULL, &text_w, NULL); - - if (mode == ALIGN_MODE_CENTRE) { - x = SCREEN_WIDTH / 2 - text_w / 2; - } else if (mode == ALIGN_MODE_RIGHT) { - x -= text_w; - } - renderTexture(image, renderer, x, y); - SDL_DestroyTexture(image); - return x + (mode == ALIGN_MODE_RIGHT? 0 : 1) * text_w; -} - -int main(void) -{ - struct clock_data l; - - /* initial unread indicator value */ - shared_data.is_unread = 0; - - strncpy(l.sunrise_time, "??:??", sizeof(l.sunrise_time)); - strncpy(l.sunset_time, "??:??", sizeof(l.sunset_time)); - l.sat_seen = 0; - l.sat_used = 0; - l.leap_second = 0; - l.offset = 0; - strncpy(l.offset_units, "?", sizeof(l.offset_units)); - l.no_gps_lock = 1; - - if (sem_init(&data_lock, 0, 1)) { - perror("sem_init"); - return 1; - } - - int stop = 0; - SDL_Event e; - SDL_Window *window; - - SDL_Init(SDL_INIT_VIDEO); - TTF_Init(); - - TTF_Font *mainTimeFont = loadFont("/usr/share/fonts/TTF/RobotoMono-Regular.ttf", 325); - TTF_Font *noLockFont = loadFont("/usr/share/fonts/TTF/Roboto-Regular.ttf", 130); - TTF_Font *secondsFont = loadFont("/usr/share/fonts/TTF/RobotoMono-Regular.ttf", 30); - - TTF_Font *dateFont = loadFont("/usr/share/fonts/TTF/Roboto-Regular.ttf", 50); - TTF_Font *dateSymbolFont = loadFont("/usr/share/fonts/TTF/Symbola.ttf", 50); - - TTF_Font *ntpInfoFont= loadFont("/usr/share/fonts/TTF/Roboto-Regular.ttf", 30); - TTF_Font *ntpSymbolFont = loadFont("/usr/share/fonts/TTF/Symbola.ttf", 30); - if ( !ntpSymbolFont - || !dateSymbolFont - || !mainTimeFont - || !dateFont - || !secondsFont - || !ntpInfoFont) { - return 1; - } - - /* launch pthread */ - pthread_t thread; - if (pthread_create(&thread, NULL, read_stats, NULL) != 0) { - perror("pthread_create"); - return 1; - } - - window = SDL_CreateWindow(WINDOW_TITLE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL); - if (!window) { - printf("Could not create window: %s\n", SDL_GetError()); - return 1; - } - - SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - if (!renderer) { - SDL_DestroyWindow(window); - printf("SDL_CreateRenderer Error\n"); - SDL_Quit(); - return 1; - } - - while (!stop) - { - while (SDL_PollEvent(&e)){ - if ( e.type == SDL_QUIT - || e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_q) { - stop = 1; - } - } - char text[64]; - time_t t; - struct tm *time_s; - - - SDL_Texture *image; - int text_w; - - SDL_RenderClear(renderer); - - t = time(NULL); - if ((time_s = localtime(&t)) == NULL) { - /* FIXME error */ - continue; - } - - int next_x = 0; - - sem_wait(&data_lock); - if (shared_data.is_unread) { - get_clock_data(&l); - shared_data.is_unread = 0; - } - sem_post(&data_lock); - - if (l.sat_seen == 0 || l.sat_used == 0 || l.no_gps_lock) { - drawText("No GPS Lock", noLockFont, COLOUR_WHITE, renderer, 0, NO_LOCK_Y, ALIGN_MODE_CENTRE); - } else { - /* Have GPS lock, go for it */ - /**/ - strftime(text, sizeof(text), "%H%M", time_s); - drawText(text, mainTimeFont, COLOUR_WHITE, renderer, TIME_X, TIME_Y, ALIGN_MODE_CENTRE); - /**/ - - /********************/ - /* Draws a date string, normally like: - * Monday the 25th - * February, 2019 - */ - strftime(text, sizeof(text), "%A", time_s); - next_x = drawText(text, dateFont, COLOUR_WHITE, renderer, DATE_1_X, DATE_1_Y, ALIGN_MODE_LEFT); - - next_x = drawText(" the ", dateFont, COLOUR_40GRAY, renderer, next_x, DATE_1_Y, ALIGN_MODE_LEFT); - - snprintf(text, sizeof(text), "%d%s", time_s->tm_mday, get_th_suffix(time_s->tm_mday)); - next_x = drawText(text, dateFont, COLOUR_WHITE, renderer, next_x, DATE_1_Y, ALIGN_MODE_LEFT); - next_x = drawText(".", dateFont, COLOUR_40GRAY, renderer, next_x, DATE_1_Y, ALIGN_MODE_LEFT); - - strftime(text, sizeof(text), "%B", time_s); - next_x = drawText(text, dateFont, COLOUR_WHITE, renderer, DATE_2_X, DATE_2_Y, ALIGN_MODE_LEFT); - - next_x = drawText(", ", dateFont, COLOUR_40GRAY, renderer, next_x, DATE_2_Y, ALIGN_MODE_LEFT); - - strftime(text, sizeof(text), "%Y", time_s); - next_x = drawText(text, dateFont, COLOUR_WHITE, renderer, next_x, DATE_2_Y, ALIGN_MODE_LEFT); - /********************/ - - /**/ - strftime(text, sizeof(text), ":%S", time_s); - next_x = drawText(text, secondsFont, COLOUR_WHITE, renderer, SECONDS_X, SECONDS_Y, ALIGN_MODE_LEFT); - /**/ - - /**/ - next_x = drawText("⏰ ", ntpSymbolFont, COLOUR_40GRAY, renderer, NTP_INFO_X, NTP_INFO_Y, ALIGN_MODE_LEFT); - snprintf(text, sizeof(text), " RMS %d %s%s ", l.offset, l.offset_units, - l.leap_second ? ", Leap second coming!" : ""); - next_x = drawText(text, ntpInfoFont, COLOUR_40GRAY, renderer, next_x, NTP_INFO_Y, ALIGN_MODE_LEFT); - /**/ - - /**/ - next_x = drawText(l.sunrise_time, dateFont, COLOUR_WHITE, renderer, SUN_INFO_X, SUN_INFO_1_Y, ALIGN_MODE_RIGHT); - next_x = drawText("☀⬆", dateSymbolFont, COLOUR_YELLOW, renderer, next_x, SUN_INFO_1_Y, ALIGN_MODE_RIGHT); - next_x = drawText(l.sunset_time, dateFont, COLOUR_WHITE, renderer, SUN_INFO_X, SUN_INFO_2_Y, ALIGN_MODE_RIGHT); - next_x = drawText("☀⬇", dateSymbolFont, COLOUR_YELLOW, renderer, next_x, SUN_INFO_2_Y, ALIGN_MODE_RIGHT); - // next_x = drawText("⭡05:45 ↓20:13", dateFont, COLOUR_WHITE, renderer, SUN_INFO_X, SUN_INFO_Y); - /**/ - } - /**/ - next_x = drawText("🛰 ", ntpSymbolFont, COLOUR_40GRAY, renderer, SAT_INFO_X, SAT_INFO_Y, ALIGN_MODE_LEFT); - snprintf(text, sizeof(text), "%d (%d used)", l.sat_seen, l.sat_used); - next_x = drawText(text, ntpInfoFont, COLOUR_40GRAY, renderer, next_x, NTP_INFO_Y, ALIGN_MODE_LEFT); - /**/ - SDL_RenderPresent(renderer); - SDL_Delay(100); - } - - SDL_DestroyWindow(window); - SDL_Quit(); - return 0; -} - -- cgit v1.1