#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct { // GMainLoop *mloop; GtkBuilder *builder; mwdevice_t mwdevice; unsigned char rcvbuf[128]; int rcvbuf_pos; int con_fd; /* console input fd */ char cmdline[128]; int cmdline_pos; int bat_timeout_id; } mwdata_t; gboolean battery_level_get_timeout(gpointer user_data) { mwdata_t *mdata = (mwdata_t *)user_data; mw_send_frame(&mdata->mwdevice, MW_READ_BATTERY_VOLTAGE_MSG, 0, NULL, 0); return TRUE; } void mw_get_battery_voltage_response_cb(mwdevice_t *mwdevice, unsigned short *voltage, unsigned char *pgood, unsigned char *charging, void *user_data) { mwdata_t *mdata = (mwdata_t *)user_data; gdouble volt = *voltage; GtkAdjustment *batadjust; GtkProgressBar *batbar; gchar batstr[32]; batadjust = GTK_ADJUSTMENT(gtk_builder_get_object (mdata->builder, "bat_adjust")); gtk_adjustment_set_value(batadjust, volt); batbar = GTK_PROGRESS_BAR(gtk_builder_get_object (mdata->builder, "battery_status_bar")); snprintf(batstr, 32, "%4.0fmV", volt); gtk_progress_bar_set_text(batbar, batstr); } void on_notify_ok_clicked (GtkButton *button, gpointer user_data) { mwdata_t *mdata = (mwdata_t *)user_data; GtkWidget *notify_win; GtkTextView *tview; GtkTextBuffer *tbuf; GtkTextIter siter, eiter; gchar *text; tview = GTK_TEXT_VIEW (gtk_builder_get_object (mdata->builder, "notify_textview")); tbuf = gtk_text_view_get_buffer(tview); gtk_text_buffer_get_start_iter(tbuf, &siter); gtk_text_buffer_get_end_iter(tbuf, &eiter); text = gtk_text_buffer_get_text(tbuf, &siter, &eiter, FALSE); mw_do_notification(&mdata->mwdevice, "Notification", text, 2); notify_win = GTK_WIDGET (gtk_builder_get_object (mdata->builder, "notify_win")); gtk_widget_hide (notify_win); } void on_notify_cancel_clicked (GtkButton *button, gpointer user_data) { mwdata_t *mdata = (mwdata_t *)user_data; GtkWidget *notify_win; notify_win = GTK_WIDGET (gtk_builder_get_object (mdata->builder, "notify_win")); gtk_widget_hide (notify_win); } void on_rtc_button_clicked (GtkButton *button, gpointer user_data) { mwdata_t *mdata = (mwdata_t *)user_data; mw_send_frame(&mdata->mwdevice, MW_GET_REAL_TIME_CLOCK, 0, NULL, 0); } void on_notify_button_clicked (GtkButton *button, gpointer user_data) { mwdata_t *mdata = (mwdata_t *)user_data; GtkWidget *notify_win; notify_win = GTK_WIDGET (gtk_builder_get_object (mdata->builder, "notify_win")); gtk_widget_show (notify_win); } void bitmap_read(mwdevice_t *mwdevice, char *filename) { int ffd, ret; char rbuf[256]; unsigned int width, height, i; #ifdef DEBUG unsigned int x, y; #endif unsigned int rowlength; unsigned char *bmapbuf; // unsigned char mw_buf[24]; ffd = open(filename, O_RDONLY); if (ffd < 0) { perror("open"); return; }; ret = read(ffd, rbuf, 3); if (rbuf[0] != 'P' || rbuf[1] != '4') { fprintf(stderr, "not a PBM file\n"); return; } memset(rbuf, 0, 256); i = 0; do { ret = read(ffd, (rbuf+i), 1); } while (!isspace(rbuf[i++])); width = atoi(rbuf); memset(rbuf, 0, 256); i = 0; do { ret = read(ffd, (rbuf+i), 1); } while (!isspace(rbuf[i++])); height = atoi(rbuf); rowlength = ((width / 8) + 1); bmapbuf = malloc(rowlength * height); ret = read(ffd, bmapbuf, rowlength * height); close(ffd); #ifdef DEBUG fprintf(stderr, "row length = %d bytes\n", rowlength); fprintf(stderr, "bitmap resolution is %d x %d\n", width, height); fprintf(stderr, "read %d of %d bytes\n", ret, rowlength * height); fprintf(stderr, "\n"); for (y=0; y 12) hour -= 12; mw_advance_watch_hands(&mdata->mwdevice, hour, (unsigned char) mtm.tm_min, (unsigned char) mtm.tm_sec); } void on_bitmap_button_clicked (GtkButton *button, gpointer user_data) { mwdata_t *mdata = (mwdata_t *)user_data; GtkWindow *mwin; GtkWidget *dialog; mwin = GTK_WINDOW (gtk_builder_get_object (mdata->builder, "main_win")); dialog = gtk_file_chooser_dialog_new("Bitmap File", mwin, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { gchar *filename; filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); /* send bitmap file */ bitmap_read(&mdata->mwdevice, filename); } gtk_widget_destroy(dialog); } void setup_watchtype_gui(mwdata_t *mdata) { GtkWidget *w; if (mdata->mwdevice.devtype == MW_DEVICE_TYPE_DIGITAL || mdata->mwdevice.devtype == MW_DEVICE_TYPE_DEVB_DIGI) { w = GTK_WIDGET (gtk_builder_get_object (mdata->builder, "set_hands")); gtk_widget_hide(w); } if (mdata->mwdevice.devtype == MW_DEVICE_TYPE_ANA_DIGI || mdata->mwdevice.devtype == MW_DEVICE_TYPE_DEVB_ANA_DIGI) { w = GTK_WIDGET (gtk_builder_get_object (mdata->builder, "F_button_label")); gtk_widget_hide(w); w = GTK_WIDGET (gtk_builder_get_object (mdata->builder, "E_button_label")); gtk_widget_hide(w); w = GTK_WIDGET (gtk_builder_get_object (mdata->builder, "D_button_label")); gtk_widget_hide(w); } } void mw_get_device_type_response_cb(mwdevice_t *mwdevice, unsigned char devtype, void *user_data) { mwdata_t *mdata = (mwdata_t *)user_data; setup_watchtype_gui(mdata); } void mw_get_real_time_clock_response_cb(mwdevice_t *mwdevice, struct tm *mw_tm, void *user_data) { mwdata_t *mdata = (mwdata_t *)user_data; GtkButton *rtc_button; gchar label_str[256]; //g_print("watch RTC is %s\n", asctime(mw_tm)); rtc_button = GTK_BUTTON (gtk_builder_get_object (mdata->builder, "rtc_button")); snprintf(label_str, 256, "RTC\n%s", asctime(mw_tm)); label_str[strlen(label_str)-1] = 0; gtk_button_set_label(rtc_button, label_str); } gboolean handle_mw_io(GIOChannel *mw_io, GIOCondition condition, gpointer udata) { mwdata_t *mdata = (mwdata_t *)udata; int rcvd; int processed; rcvd = read(mdata->mwdevice.mw_fd, mdata->rcvbuf/*+mdata->rcvbuf_pos*/, 64); #ifdef DEBUG fprintf(stderr, "read %d bytes:\n", rcvd); #endif if (rcvd > 0) { #ifdef DEBUG dump_frame(mdata->rcvbuf, rcvd); #endif processed = decode_frame(&mdata->mwdevice, mdata->rcvbuf, rcvd); if (processed > 0) { mdata->rcvbuf_pos -= processed; if (mdata->rcvbuf_pos > 0) g_print("Warning: RCV buffer not yet empty\n"); } else { /* we should rather seek forward for a next potential frame start */ mdata->rcvbuf_pos = 0; } } return TRUE; } void on_window_destroy (GtkObject *object, gpointer user_data) { gtk_main_quit (); } int main (int argc, char *argv[]) { GtkBuilder *builder; GtkWidget *window; GIOChannel *mw_io; bdaddr_t btaddr; int mw_fd; struct termios tmwfd; mwdata_t mdata; if (argc != 2) { fprintf(stderr, "Usage:\n\t%s \n", argv[0]); return 1; }; crc16ccitt_init(); if (str2ba(argv[1], &btaddr)) return 1; mw_fd = open_socket(&btaddr, 1); if (mw_fd < 0) { return 1; } else { fprintf(stderr, "connected to %s\n", argv[1]); }; /* we have a connection, RFCOMM socket is on mw_fd */ /* make the tty raw */ tcgetattr(mw_fd, &tmwfd); cfmakeraw(&tmwfd); tmwfd.c_oflag |= ONLCR | OPOST; tmwfd.c_lflag |= ISIG; tcsetattr(mw_fd, TCSANOW, &tmwfd); mdata.mwdevice.mw_fd = mw_fd; mdata.rcvbuf_pos = 0; memset(mdata.rcvbuf, 0, 128); gtk_init (&argc, &argv); builder = gtk_builder_new (); gtk_builder_add_from_file (builder, "mw-client.glade", NULL); mdata.builder = builder; window = GTK_WIDGET (gtk_builder_get_object (builder, "main_win")); gtk_builder_connect_signals (builder, &mdata); //g_object_unref (G_OBJECT (builder)); gtk_widget_show (window); mw_io = g_io_channel_unix_new(mw_fd); g_io_add_watch(mw_io, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP, handle_mw_io, &mdata); mw_init(&mdata.mwdevice, mw_fd); mw_set_get_device_type_response_cb(&mdata.mwdevice, mw_get_device_type_response_cb, &mdata); mw_set_get_real_time_clock_response_cb(&mdata.mwdevice, mw_get_real_time_clock_response_cb, &mdata); mw_set_get_battery_voltage_response_cb(&mdata.mwdevice, mw_get_battery_voltage_response_cb, &mdata); // mw_send_frame(&mdata.mwdevice, MW_READ_BATTERY_VOLTAGE_MSG, 0, NULL, 0); mdata.bat_timeout_id = g_timeout_add_seconds(10, battery_level_get_timeout, &mdata); // setup_watchtype_gui(&mdata); gtk_main (); return 0; }