Toast notification daemon

This commit is contained in:
Kevin Lange 2014-04-21 19:46:38 -07:00
parent c31bedd69e
commit 1b3dcea6a1
8 changed files with 269 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

39
userspace/extra/toast.c Normal file
View File

@ -0,0 +1,39 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lib/pex.h"
#include "lib/toastd.h"
int main(int argc, char * argv[]) {
if (argc < 3) {
fprintf(stderr, "%s: \"title\" \"message\"\n", argv[0]);
return 1;
}
char * server = getenv("TOASTD");
if (!server) {
server = "toastd"; /* Appropriate fallback */
}
FILE * c = pex_connect(server);
if (!c) {
fprintf(stderr, "%s: Could not connect to toast daemon.\n", argv[0]);
return 1;
}
int size = strlen(argv[1]) + strlen(argv[2]) + 2 + sizeof(notification_t);
notification_t * note = malloc(size);
note->ttl = 5; /* seconds */
memcpy(note->strings, argv[1], strlen(argv[1])+1);
memcpy(note->strings + strlen(argv[1])+1, argv[2], strlen(argv[2])+1);
pex_reply(c, size, (void*)note);
return 0;
}

View File

@ -64,6 +64,11 @@ int main(int argc, char * argv[]) {
char * args[] = {"/bin/panel", NULL};
execvp(args[0], args);
}
int _toastd_pid = fork();
if (!_toastd_pid) {
char * args[] = {"/bin/toastd", NULL};
execvp(args[0], args);
}
syscall_wait(_panel_pid);

194
userspace/gui/core/toastd.c Normal file
View File

@ -0,0 +1,194 @@
/* vim: tabstop=4 shiftwidth=4 noexpandtab
*
* Toast (Notification) Daemon
*
*/
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <math.h>
#include <signal.h>
#include <time.h>
#include "lib/yutani.h"
#include "lib/graphics.h"
#include "lib/shmemfonts.h"
#include "lib/pex.h"
#include "lib/pthread.h"
#include "lib/spinlock.h"
#include "lib/toastd.h"
static yutani_t * yctx;
static list_t * notifications;
static FILE * toastd_server;
static int notification_lock = 0;
static int exit_app = 0;
static sprite_t * toast_bg;
#define TOASTD_NAME "toastd"
#define TOAST_WIDTH 310
#define TOAST_HEIGHT 110
#define TOAST_PAD 20
typedef struct {
int ttl;
char * title;
char * content;
yutani_window_t * window;
int stack;
} notification_int_t;
static void add_toast(notification_t * incoming) {
notification_int_t * toast = malloc(sizeof(notification_int_t));
toast->ttl = incoming->ttl + time(NULL);
toast->title = strdup(incoming->strings);
toast->content = strdup(incoming->strings + 1 + strlen(incoming->strings));
fprintf(stderr, "ttl=%d, title=\"%s\" content=\"%s\"\n", toast->ttl, toast->title, toast->content);
spin_lock(&notification_lock);
toast->window = yutani_window_create(yctx, TOAST_WIDTH, TOAST_HEIGHT);
/* Find best location */
int i = 0, hit_something = 1;
while (hit_something) {
hit_something = 0;
foreach(node, notifications) {
notification_int_t * toast = node->value;
if (toast->stack == i) {
i++;
hit_something = 1;
}
}
}
toast->stack = i;
yutani_window_move(yctx, toast->window, yctx->display_width - TOAST_WIDTH - 20, 30 + (TOAST_HEIGHT + TOAST_PAD) * i);
gfx_context_t * ctx = init_graphics_yutani(toast->window);
draw_sprite(ctx, toast_bg, 0, 0);
set_font_face(FONT_SANS_SERIF_BOLD);
set_font_size(14);
draw_string(ctx, 20, 22, rgb(255,255,255), toast->title);
char * str = toast->content;
char * end = toast->content + strlen(toast->content);
unsigned int line = 0;
while (str) {
char * next = strstr(str, "\n");
if (next) {
next[0] = '\0';
next++;
}
set_font_face(FONT_SANS_SERIF);
set_font_size(12);
draw_string(ctx, 20, 40 + line * 14, rgb(255,255,255), str);
str = next;
line++;
}
free(ctx);
yutani_flip(yctx, toast->window);
list_insert(notifications, toast);
spin_unlock(&notification_lock);
}
static void * toastd_handler(void * garbage) {
(void)garbage;
setenv("TOASTD", TOASTD_NAME, 1);
toastd_server = pex_bind(TOASTD_NAME);
while (!exit_app) {
pex_packet_t * p = calloc(PACKET_SIZE, 1);
pex_listen(toastd_server, p);
notification_t * toast = (void *)p->data;
add_toast(toast);
free(p);
}
}
static void * closer_handler(void * garbage) {
while (!exit_app) {
time_t now = time(NULL);
spin_lock(&notification_lock);
list_t * tmp = list_create();
foreach(node, notifications) {
notification_int_t * toast = node->value;
if (toast->window && toast->ttl <= now) {
yutani_close(yctx, toast->window);
free(toast->title);
free(toast->content);
list_insert(tmp, node);
}
}
foreach(node, tmp) {
list_delete(notifications, node->value);
}
list_free(tmp);
free(tmp);
spin_unlock(&notification_lock);
usleep(500000);
}
foreach(node, notifications) {
notification_int_t * toast = node->value;
if (toast->window) {
yutani_close(yctx, toast->window);
}
}
}
int main (int argc, char ** argv) {
yctx = yutani_init();
notifications = list_create();
toast_bg = malloc(sizeof(sprite_t));
load_sprite_png(toast_bg, "/usr/share/ttk/toast/default.png");
init_shmemfonts();
pthread_t toastd_thread;
pthread_create(&toastd_thread, NULL, toastd_handler, NULL);
pthread_t closer_thread;
pthread_create(&closer_thread, NULL, closer_handler, NULL);
while (!exit_app) {
yutani_msg_t * m = yutani_poll(yctx);
if (m) {
switch (m->type) {
case YUTANI_MSG_SESSION_END:
exit_app = 1;
break;
}
free(m);
}
}
pthread_kill(toastd_thread, SIGWINCH);
pthread_kill(closer_thread, SIGWINCH);
return 0;
}

View File

@ -1,6 +1,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <syscall.h>
#include <signal.h>
#include "pthread.h"
#define PTHREAD_STACK_SIZE 0x100000
@ -20,6 +21,10 @@ int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *(*start_rout
return 0;
}
int pthread_kill(pthread_t thread, int sig) {
return kill(thread.id, sig);
}
void pthread_exit(void * value) {
/* Perform nice cleanup */
#if 0

View File

@ -13,6 +13,7 @@ typedef unsigned int pthread_attr_t;
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg);
void pthread_exit(void * value);
int pthread_kill(pthread_t thread, int sig);
int clone(uintptr_t,uintptr_t,void*);
int gettid();

16
userspace/lib/spinlock.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef _SPINLOCK_H_
#define _SPINLOCK_H_
#ifndef spin_lock
static void spin_lock(int volatile * lock) {
while(__sync_lock_test_and_set(lock, 0x01)) {
syscall_yield();
}
}
static void spin_unlock(int volatile * lock) {
__sync_lock_release(lock);
}
#endif
#endif /* _SPINLOCK_H */

9
userspace/lib/toastd.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _TOASTD_H_
#define _TOASTD_H_
typedef struct {
unsigned int ttl;
char strings[];
} notification_t;
#endif /* _TOASTD_H_ */