From 31eb47ce4b6aa0e19e05cc906964780be6233acd Mon Sep 17 00:00:00 2001 From: nick Date: Thu, 28 Feb 2008 20:16:11 +0000 Subject: [PATCH] xcowsay 0.4 released git-svn-id: http://svn.nickg.me.uk/work/xcowsay@279 a97b1542-0b21-0410-a459-e47997c36f34 --- Makefile.am | 2 +- configure.ac | 2 +- display_cow.c | 56 ++++++++++++++++++++++++++++++++++++++++++--------- display_cow.h | 7 ++++++- xcowat | 13 +++++++++++- xcowsay.c | 24 ++++++++++++++++++---- xcowsayd.c | 12 ++++++----- 7 files changed, 93 insertions(+), 23 deletions(-) diff --git a/Makefile.am b/Makefile.am index 83b1b7c..90fde6a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,4 +9,4 @@ xcowsay_SOURCES = xcowsay.c display_cow.c display_cow.h floating_shape.h \ xcowsayd.c dist_pkgdata_DATA = cow_small.png cow_med.png cow_large.png -EXTRA_DIST = cow.svg +EXTRA_DIST = cow.svg xcowat xcowfortune diff --git a/configure.ac b/configure.ac index af91519..471c3f2 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([xcowsay], [0.3.1], +AC_INIT([xcowsay], [0.4], [Nick Gasson ], [xcowsay]) AM_INIT_AUTOMAKE([-Wall]) diff --git a/display_cow.c b/display_cow.c index 71f0f09..e2b024b 100644 --- a/display_cow.c +++ b/display_cow.c @@ -38,6 +38,7 @@ typedef struct { GdkPixbuf *cow_pixbuf, *bubble_pixbuf; cowstate_t state; int transition_timeout; + int display_time; } xcowsay_t; static xcowsay_t xcowsay; @@ -238,7 +239,7 @@ static gboolean tick(gpointer data) exit(EXIT_FAILURE); case csDisplay: show_shape(xcowsay.bubble); - xcowsay.transition_timeout = get_int_option("display_time"); + xcowsay.transition_timeout = xcowsay.display_time; break; case csLeadOut: hide_shape(xcowsay.bubble); @@ -266,14 +267,29 @@ void cowsay_init(int *argc, char ***argv) xcowsay.cow_pixbuf = load_cow(); } -char *copy_string(const char *s) +static char *copy_string(const char *s) { char *copy = malloc(strlen(s)+1); strcpy(copy, s); return copy; } -void display_cow(const char *text) +static int count_words(const char *s) +{ + bool last_was_space = false; + int words; + for (words = 1; *s; s++) { + if (isspace(*s) && !last_was_space) { + words++; + last_was_space = true; + } + else + last_was_space = false; + } + return words; +} + +void display_cow(bool debug, const char *text) { char *text_copy = copy_string(text); @@ -282,6 +298,29 @@ void display_cow(const char *text) if ('\n' == text_copy[len-1]) text_copy[len-1] = '\0'; + // Count the words and work out the display time, if neccessary + xcowsay.display_time = get_int_option("display_time"); + if (xcowsay.display_time < 0) { + int words = count_words(text_copy); + xcowsay.display_time = words * get_int_option("reading_speed"); + debug_msg("Calculated display time as %dms from %d words\n", + xcowsay.display_time, words); + } + else { + debug_msg("Using default display time %dms\n", xcowsay.display_time); + } + + int min_display = get_int_option("min_display_time"); + int max_display = get_int_option("max_display_time"); + if (xcowsay.display_time < min_display) { + xcowsay.display_time = min_display; + debug_msg("Display time too short: clamped to %d\n", min_display); + } + else if (xcowsay.display_time > max_display) { + xcowsay.display_time = max_display; + debug_msg("Display time too long: clamped to %d\n", max_display); + } + xcowsay.bubble_pixbuf = create_bubble(text_copy); free(text_copy); @@ -319,8 +358,7 @@ void display_cow(const char *text) bool try_dbus(bool debug, const char *text) { - if (debug) - printf("Skipping DBus (disabled by configure)\n"); + debug_msg("Skipping DBus (disabled by configure)\n"); return false; } @@ -336,8 +374,7 @@ bool try_dbus(bool debug, const char *text) error = NULL; connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); if (NULL == connection) { - if (debug) - g_printerr("Failed to open connection to bus: %s\n", error->message); + debug_err("Failed to open connection to bus: %s\n", error->message); g_error_free(error); return false; } @@ -349,8 +386,7 @@ bool try_dbus(bool debug, const char *text) error = NULL; if (!dbus_g_proxy_call(proxy, "ShowCow", &error, G_TYPE_STRING, text, G_TYPE_INVALID, G_TYPE_INVALID)) { - if (debug) - g_printerr("ShowCow failed: %s\n", error->message); + debug_err("ShowCow failed: %s\n", error->message); g_error_free(error); return false; } @@ -363,5 +399,5 @@ bool try_dbus(bool debug, const char *text) void display_cow_or_invoke_daemon(bool debug, const char *text) { if (!try_dbus(debug, text)) - display_cow(text); + display_cow(debug, text); } diff --git a/display_cow.h b/display_cow.h index db9b23c..5da0cb6 100644 --- a/display_cow.h +++ b/display_cow.h @@ -6,8 +6,13 @@ #include #include +#define CALCULATE_DISPLAY_TIME -1 // Work out display time from word count + +#define debug_msg(...) if (debug) printf(__VA_ARGS__); +#define debug_err(...) if (debug) g_printerr(__VA_ARGS__); + // Show a cow with the given string and clean up afterwards -void display_cow(const char *text); +void display_cow(bool debug, const char *text); void display_cow_or_invoke_daemon(bool debug, const char *text); void cowsay_init(int *argc, char ***argv); diff --git a/xcowat b/xcowat index 33209e1..539188a 100755 --- a/xcowat +++ b/xcowat @@ -4,4 +4,15 @@ # Run xcowsay at the specified time using atd # -echo "xcowsay \"$2\"" | at $1 +# Might not have a display +if [ "$DISPLAY" == "" ]; then + export DISPLAY=:0.0 +fi + +# xcowsay may not be on the PATH... +# ...but it should be in the same directory as xcowat +PATH=$PATH:`dirname $0` + +export PATH + +echo "DISPLAY=$DISPLAY env xcowsay \"$2\"" | at $1 diff --git a/xcowsay.c b/xcowsay.c index dc7c62d..693d8ee 100644 --- a/xcowsay.c +++ b/xcowsay.c @@ -9,9 +9,12 @@ // Default settings #define DEF_LEAD_IN_TIME 250 -#define DEF_DISPLAY_TIME 4000 +#define DEF_DISPLAY_TIME CALCULATE_DISPLAY_TIME #define DEF_LEAD_OUT_TIME LEAD_IN_TIME -#define DEF_FONT "Bitstream Vera Sans 14" +#define DEF_MIN_TIME 1000 +#define DEF_MAX_TIME 30000 +#define DEF_FONT "Bitstream Vera Sans 14" +#define DEF_READING_SPEED 250 // Human average is apparently 200-250 WPM (=4 WPS) #define MAX_STDIN 4096 // Maximum chars to read from stdin @@ -22,6 +25,7 @@ static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"time", required_argument, 0, 't'}, {"font", required_argument, 0, 'f'}, + {"reading-speed", required_argument, 0, 'r'}, {"daemon", no_argument, &daemon_flag, 1}, {"debug", no_argument, &debug, 1}, {0, 0, 0, 0} @@ -49,9 +53,15 @@ static void usage() "Options:\n" " -h, --help\t\tDisplay this message and exit.\n" " -t, --time=SECONDS\tDisplay message for SECONDS seconds.\n" + " -r, --reading-speed=N\tNumber of milliseconds to delay per word.\n" " -f, --font=FONT\tSet message font (Pango format).\n" " -d, --daemon\t\tRun xcowsay in daemon mode.\n" - " --debug\t\tKeep daemon attached to terminal.\n"; + " --debug\t\tKeep daemon attached to terminal.\n\n" + "Default values for these options can be specified in the xcowsay config\n" + "file. See the manpage for more information [Or not... ;-)]\n\n" + "If the display_time option is not set the display time will be calcuated\n" + "from the reading_speed parameter multiplied by the word count.\n\n" + "Report bugs to nick@cakesniffer.co.uk"; puts(usage_message); } @@ -72,10 +82,13 @@ int main(int argc, char **argv) add_int_option("lead_in_time", DEF_LEAD_IN_TIME); add_int_option("display_time", DEF_DISPLAY_TIME); add_int_option("lead_out_time", get_int_option("lead_in_time")); + add_int_option("min_display_time", DEF_MIN_TIME); + add_int_option("max_display_time", DEF_MAX_TIME); + add_int_option("reading_speed", DEF_READING_SPEED); add_string_option("font", DEF_FONT); int c, index = 0, failure = 0; - const char *spec = "hdt:f:"; + const char *spec = "hdrt:f:"; while ((c = getopt_long(argc, argv, spec, long_options, &index)) != -1) { switch (c) { case 0: @@ -90,6 +103,9 @@ int main(int argc, char **argv) case 't': set_int_option("display_time", parse_int_option(optarg)*1000); break; + case 'r': + set_int_option("reading_speed", parse_int_option(optarg)); + break; case 'f': set_string_option("font", optarg); break; diff --git a/xcowsayd.c b/xcowsayd.c index 8eb3313..985d7db 100644 --- a/xcowsayd.c +++ b/xcowsayd.c @@ -98,17 +98,19 @@ static void request_complete() static gpointer cow_display_thread(gpointer data) { - printf("In the cow display thread\n"); + bool debug = *(bool*)data; + + debug_msg("In the cow display thread\n"); for (;;) { const char *mess = wait_for_request(); - printf("Processing request: %s\n", mess); + debug_msg("Processing request: %s\n", mess); // We need to wrap the GTK+ stuff in gdk_threads_X since // GTK assumes it is being called from the main thread // (and it isn't here) gdk_threads_enter(); - display_cow(mess); + display_cow(debug, mess); gdk_threads_leave(); request_complete(); @@ -213,10 +215,10 @@ void run_cowsay_daemon(bool debug, int argc, char **argv) g_type_init(); Cowsay *server = g_object_new(cowsayd_get_type(), NULL); - GThread *displ = g_thread_create(cow_display_thread, NULL, FALSE, NULL); + GThread *displ = g_thread_create(cow_display_thread, (gpointer)&debug, FALSE, NULL); g_assert(displ); - printf("Cowsay daemon starting...\n"); + debug_msg("Cowsay daemon starting...\n"); GMainLoop *main_loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(main_loop); -- 2.39.2