Janis Streib
30.03.22 00027aa5bb1da6f2d44c03a082988de8c64dab4a
Commit | Autor | Alter
8c7455 1 // G4Term.cpp
JS 2
3 #include <gtk/gtk.h>
4 #include "G4TrackIncl.h"
5 #include <pthread.h>
6 #include <time.h>
7 #include <stdlib.h>
8 #include <errno.h>
9 #include "G4Term.h"
10 #include "PingPong.h"
11 #include "IncrDlg.h"
12 #include "FrameDlg.h"
13 #include "FilterDlg.h"
14 #include "UnitsDlg.h"
15 #include <string.h>
16 #include "config.h"
17
18
19
20
21 const char* piterm_version=VERSION;
22 const char* piterm_comment="Terminal program to communicate with the Polhemus G4 Tracker";
23
24 enum {CNX_BUT,DNX_BUT,SINGLE_BUT,START_BUT,STOP_BUT,NUMBUTTONS};
25 pthread_t contThread;
26 int gRunCont=0;
27 int gConnected=0;
28 pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
29
30 int isQuats=0;
31 int sysId;
32
33
34
35 typedef struct _THREADINFO {
36   PingPong pp;
37   GtkWidget* text;
38   FILE* fCap;
39 }THREADINFO;
40
41 typedef struct _FILEINFO {
42   FILE* f;
43   char filename[200];
44 }FILEINFO;
45
46 int main(int argc,char* argv[]){
47
48
49   GtkWidget* win;
50   GtkWidget* butArr[NUMBUTTONS];
51   GtkWidget *cnx_but_box,*act_button_box,*vbox,*hbox,*cfg_button_box;
52   GtkWidget* textview,*scrWin;
53   GtkWidget *capture,*boresight,*unboresight,*rotate,*translate,*filter,*incr,*units,*clear,*about,*quit;
54   GtkWidget* image;
55
56   FILEINFO fi;
57   fi.f=NULL;
58   memset(fi.filename,0,sizeof(fi.filename));
59
60   gtk_init(&argc,&argv);
61
62   // This should have defaulted to true, but it didn't
63   g_object_set(gtk_settings_get_default(),"gtk-button_images",TRUE,NULL);
64
65   win=gtk_window_new(GTK_WINDOW_TOPLEVEL);
66   gtk_window_set_title(GTK_WINDOW(win),"Polhemus G4 Terminal");
67   gtk_container_set_border_width(GTK_CONTAINER(win),10);
68   gtk_window_set_position(GTK_WINDOW(win),GTK_WIN_POS_CENTER);
69
70   vbox=gtk_box_new(GTK_ORIENTATION_VERTICAL,10);
71   gtk_box_set_homogeneous(GTK_BOX(vbox),FALSE);
72
73   hbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,10);
74   gtk_box_set_homogeneous(GTK_BOX(hbox),FALSE);
75
76
77   // connection buttons
78   cnx_but_box=gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
79   gtk_button_box_set_layout(GTK_BUTTON_BOX(cnx_but_box),GTK_BUTTONBOX_SPREAD);
80   butArr[CNX_BUT]=gtk_button_new_from_stock(GTK_STOCK_CONNECT);
81   butArr[DNX_BUT]=gtk_button_new_from_stock(GTK_STOCK_DISCONNECT);
82   gtk_container_add(GTK_CONTAINER(cnx_but_box),butArr[CNX_BUT]);
83   gtk_container_add(GTK_CONTAINER(cnx_but_box),butArr[DNX_BUT]);
84   gtk_widget_set_sensitive(butArr[DNX_BUT],FALSE);
85
86   g_signal_connect(butArr[CNX_BUT],"clicked",G_CALLBACK(OnCnx),butArr);
87   g_signal_connect(butArr[DNX_BUT],"clicked",G_CALLBACK(OnDnx),butArr);
88
89   gtk_box_pack_start(GTK_BOX(vbox),cnx_but_box,FALSE,FALSE,10);
90
91   // action buttons
92   act_button_box=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,10);
93   butArr[SINGLE_BUT]=gtk_button_new_with_label("Single Frame");
94   butArr[START_BUT]=gtk_button_new_with_label("Start Continuous");
95   butArr[STOP_BUT]=gtk_button_new_with_label("Stop Continuous");
96   gtk_box_pack_start(GTK_BOX(act_button_box),butArr[SINGLE_BUT],TRUE,TRUE,10);
97   gtk_box_pack_start(GTK_BOX(act_button_box),butArr[START_BUT],TRUE,TRUE,10);
98   gtk_box_pack_start(GTK_BOX(act_button_box),butArr[STOP_BUT],TRUE,TRUE,10);
99   gtk_box_pack_start(GTK_BOX(vbox),act_button_box,FALSE,FALSE,10);
100   gtk_widget_set_sensitive(butArr[SINGLE_BUT],FALSE);
101   gtk_widget_set_sensitive(butArr[START_BUT],FALSE);
102   gtk_widget_set_sensitive(butArr[STOP_BUT],FALSE);
103
104
105   g_object_set_data(G_OBJECT(butArr[START_BUT]),"stop_but",(gpointer)butArr[STOP_BUT]);
106
107
108
109
110
111   // output window
112   scrWin=gtk_scrolled_window_new(NULL,NULL);
113   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrWin),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
114   gtk_widget_set_size_request(scrWin,700,500);
115   textview=gtk_text_view_new();
116   gtk_text_view_set_editable(GTK_TEXT_VIEW(textview),FALSE);
117   gtk_container_add(GTK_CONTAINER(scrWin),textview);
118   gtk_box_pack_start(GTK_BOX(vbox),scrWin,TRUE,TRUE,10);
119
120   g_object_set_data(G_OBJECT(butArr[SINGLE_BUT]),"file",&fi);
121   g_object_set_data(G_OBJECT(butArr[START_BUT]),"file",&fi);
122   g_signal_connect_swapped(butArr[SINGLE_BUT],"clicked",G_CALLBACK(OnSingle),textview);
123   g_signal_connect_swapped(butArr[START_BUT],"clicked",G_CALLBACK(OnStartCont),textview);
124   g_signal_connect(butArr[STOP_BUT],"clicked",G_CALLBACK(OnStopCont),(gpointer)butArr[START_BUT]);
125
126
127   gtk_box_pack_start(GTK_BOX(hbox),vbox,TRUE,TRUE,10);
128
129   //config buttons
130   cfg_button_box=gtk_button_box_new(GTK_ORIENTATION_VERTICAL);
131   gtk_button_box_set_layout(GTK_BUTTON_BOX(cfg_button_box),GTK_BUTTONBOX_CENTER);
132   capture=gtk_button_new_with_label("Capture...");
133   image=gtk_image_new_from_stock(GTK_STOCK_FLOPPY,GTK_ICON_SIZE_BUTTON);
134   gtk_button_set_image(GTK_BUTTON(capture),image);
135   boresight=gtk_button_new_with_label("Boresight");
136   unboresight=gtk_button_new_with_label("Unboresight");
137   rotate=gtk_button_new_with_label("Frame Rotation");
138   translate=gtk_button_new_with_label("Frame Translation");
139   filter=gtk_button_new_with_label("Filters");
140   incr=gtk_button_new_with_label("Increments");
141   units=gtk_button_new_with_label("Units");
142   clear=gtk_button_new_from_stock(GTK_STOCK_CLEAR);
143   about=gtk_button_new_from_stock(GTK_STOCK_ABOUT);
144   quit=gtk_button_new_from_stock(GTK_STOCK_CLOSE);
145
146   gtk_container_add(GTK_CONTAINER(cfg_button_box),capture);
147   gtk_container_add(GTK_CONTAINER(cfg_button_box),boresight);
148   gtk_container_add(GTK_CONTAINER(cfg_button_box),unboresight);
149   gtk_container_add(GTK_CONTAINER(cfg_button_box),rotate);
150   gtk_container_add(GTK_CONTAINER(cfg_button_box),translate);
151   gtk_container_add(GTK_CONTAINER(cfg_button_box),filter);
152   gtk_container_add(GTK_CONTAINER(cfg_button_box),incr);
153   gtk_container_add(GTK_CONTAINER(cfg_button_box),units);
154   gtk_container_add(GTK_CONTAINER(cfg_button_box),clear);
155   gtk_container_add(GTK_CONTAINER(cfg_button_box),about);
156   gtk_container_add(GTK_CONTAINER(cfg_button_box),quit);
157
158   gtk_box_pack_start(GTK_BOX(hbox),cfg_button_box,FALSE,FALSE,10);
159
160
161   gtk_container_add(GTK_CONTAINER(win),hbox);
162
163   g_signal_connect(capture,"clicked",G_CALLBACK(OnCapture),&fi);
164   g_signal_connect(boresight,"clicked",G_CALLBACK(OnBoresight),(gpointer)1);
165   g_signal_connect(unboresight,"clicked",G_CALLBACK(OnBoresight),(gpointer)0);
166   g_signal_connect(rotate,"clicked",G_CALLBACK(OnRotate),NULL);
167   g_signal_connect(translate,"clicked",G_CALLBACK(OnTranslate),NULL);
168   g_signal_connect(filter,"clicked",G_CALLBACK(OnFilter),NULL);
169   g_signal_connect(incr,"clicked",G_CALLBACK(OnIncr),NULL);
170   g_signal_connect(clear,"clicked",G_CALLBACK(OnClear),(gpointer)textview);
171   g_signal_connect(about,"clicked",G_CALLBACK(OnAbout),(gpointer)win);
172   g_signal_connect(units,"clicked",G_CALLBACK(OnUnits),win);
173
174
175
176   gtk_widget_show_all(win);
177
178
179   g_signal_connect(win,"destroy",G_CALLBACK(OnClose),NULL);
180   g_signal_connect(quit,"clicked",G_CALLBACK(OnClose),NULL);
181
182   gtk_main();
183
184   if (fi.f)
185     fclose(fi.f);
186
187   return 0;
188
189 }
190
191
192 void OnCnx(GtkWidget* w,gpointer g){
193
194   int rv;
195   GtkWidget* mb,*fdlg;
196   GtkWidget** buttons=(GtkWidget**)g;
197   gchar* filename;
198   GtkFileFilter* filter1,*filter2;
199
200   // query for the source config file to use
201   fdlg=gtk_file_chooser_dialog_new("Choose Source Configuration File",NULL,GTK_FILE_CHOOSER_ACTION_OPEN,
202                 GTK_STOCK_OK,GTK_RESPONSE_ACCEPT,GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL,NULL);
203
204   filter1=gtk_file_filter_new();
205   gtk_file_filter_add_pattern(filter1,"*.g4c");
206   gtk_file_filter_set_name(filter1,"G4 Source Cfg File");
207   filter2=gtk_file_filter_new();
208   gtk_file_filter_add_pattern(filter2,"*.*");
209   gtk_file_filter_set_name(filter2,"All Files");
210
211
212   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fdlg),filter1);
213   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fdlg),filter2);
214   if (gtk_dialog_run(GTK_DIALOG(fdlg))==GTK_RESPONSE_CANCEL){
215     gtk_widget_destroy(fdlg);
216     return;
217   }
218
219   filename=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fdlg));
220   gtk_widget_destroy(fdlg);
221   if (filename==NULL)
222     return;
223
224
225
226   // connect to G4
227   rv=g4_init_sys(&sysId,filename,NULL);
228   g_free(filename);
229   if (rv!=G4_ERROR_NONE){
230     mb=gtk_message_dialog_new(NULL,GTK_DIALOG_MODAL,GTK_MESSAGE_WARNING,GTK_BUTTONS_OK,"Error connecting to G4 Tracker\nError: %d",rv);
231     gtk_dialog_run(GTK_DIALOG(mb));
232     gtk_widget_destroy(mb);
233     return;
234   }
235
236
237   gtk_widget_set_sensitive(w,FALSE);
238   gtk_widget_set_sensitive(buttons[DNX_BUT],TRUE);
239   gtk_widget_set_sensitive(buttons[SINGLE_BUT],TRUE);
240   gtk_widget_set_sensitive(buttons[START_BUT],TRUE);
241   gConnected=1;
242
243 }
244
245
246 void OnDnx(GtkWidget* w,gpointer g){
247
248   GtkWidget** buttons=(GtkWidget**)g;
249
250   // disconnect from G4
251   g4_close_tracker();
252
253   gtk_widget_set_sensitive(w,FALSE);
254   gtk_widget_set_sensitive(buttons[CNX_BUT],TRUE);
255   gtk_widget_set_sensitive(buttons[SINGLE_BUT],FALSE);
256   gtk_widget_set_sensitive(buttons[START_BUT],FALSE);
257   gtk_widget_set_sensitive(buttons[STOP_BUT],FALSE);
258   gConnected=0;
259
260 }
261
262 void OnSingle(GtkWidget* textview,gpointer w){
263
264   GtkWidget* dlg;
265   // get a list of actual hubs
266   int hubs,res;
267   G4_CMD_STRUCT cs;
268   FILEINFO* pfi=(FILEINFO*)g_object_get_data(G_OBJECT(w),"file");
269   cs.cmd=G4_CMD_GET_ACTIVE_HUBS;
270   cs.cds.id=G4_CREATE_ID(sysId,0,0);
271   cs.cds.action=G4_ACTION_GET;
272   cs.cds.pParam=NULL;
273   g4_set_query(&cs);
274   hubs=cs.cds.iParam;
275
276   if (hubs==0){
277     dlg=gtk_message_dialog_new(NULL,GTK_DIALOG_MODAL,GTK_MESSAGE_WARNING,GTK_BUTTONS_OK,
278                    "No Hubs Detected");
279     gtk_dialog_run(GTK_DIALOG(dlg));
280     gtk_widget_destroy(dlg);
281     return;
282   }
283
284   int* hubList=new int[hubs];
285
286   cs.cds.pParam=hubList;
287   res=g4_set_query(&cs);
288   G4_FRAMEDATA* fd=new G4_FRAMEDATA[hubs];
289
290
291
292
293   res=g4_get_frame_data(fd,sysId,hubList,hubs);
294   res&=0xffff;
295   if (res)
296     OutputData(textview,fd,hubs,pfi->f);
297
298   delete[] fd;
299   delete[] hubList;
300 }
301 int count1=0;
302 void OutputData(GtkWidget* textview,G4_FRAMEDATA* fd,int num,FILE* f){
303
304   GtkTextBuffer* buffer;
305   GtkTextIter iter;
306   GtkTextMark* mark;
307   char buf[500];
308   int len;
309
310
311
312   for (int i=0;i<num;i++){
313     for (int a=0;a<G4_SENSORS_PER_HUB;a++){
314       if (fd[i].stationMap & (0x01<<a)){
315     if (!isQuats)
316       // {unsigned short fr=fd[i].sfd[a].pos[0]/39.37f*32767.0f/8.0f;
317       // sprintf(buf,"Hub %d, Sensor %d, %u --  %u  %.3f  %.3f  %.3f  %.3f  %.3f\n",fd[i].hub,a+1,
318       //       fd[i].frame,fr,fd[i].sfd[a].pos[1],fd[i].sfd[a].pos[2],fd[i].sfd[a].ori[0],
319       //       fd[i].sfd[a].ori[1],fd[i].sfd[a].ori[2]);}
320       len=sprintf(buf,"Hub %d, Sensor %d, %u --  %.3f  %.3f  %.3f  %.3f  %.3f  %.3f\n",fd[i].hub,a+1,
321             fd[i].frame,fd[i].sfd[a].pos[0],fd[i].sfd[a].pos[1],fd[i].sfd[a].pos[2],fd[i].sfd[a].ori[0],
322             fd[i].sfd[a].ori[1],fd[i].sfd[a].ori[2]);
323     else
324       len=sprintf(buf,"Hub %d, Sensor %d, %u --  %.3f  %.3f  %.3f  %.3f  %.3f  %.3f  %.3f\n",fd[i].hub,a+1,
325           fd[i].frame, fd[i].sfd[a].pos[0],fd[i].sfd[a].pos[1],fd[i].sfd[a].pos[2],fd[i].sfd[a].ori[0],
326           fd[i].sfd[a].ori[1],fd[i].sfd[a].ori[2],fd[i].sfd[a].ori[3]);
327
328     //write to display
329     buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
330     gtk_text_buffer_get_end_iter(buffer,&iter);
331     gtk_text_buffer_insert(buffer,&iter,buf,-1);
332
333     // scroll it down every 500 if cont
334     if (!gRunCont || (!count1++%500==0)){
335     mark=gtk_text_buffer_create_mark(buffer,"mark",&iter,TRUE);
336     gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(textview),mark);
337     gtk_text_buffer_delete_mark(buffer,mark);
338     if (f)
339       fwrite(buf,1,len,f);
340     }
341       }// End if
342     }// end a
343   }// end i
344 }
345
346
347 void OnClear(GtkWidget* w,gpointer g){
348
349   GtkTextView* text=GTK_TEXT_VIEW(g);
350   GtkTextBuffer* buffer=gtk_text_view_get_buffer(text);
351   gtk_text_buffer_set_text(buffer,"",-1);
352 }
353
354
355 void OnStartCont(GtkWidget* textview,gpointer g){
356
357   GtkWidget* stopButton;
358   // get hub list
359
360   THREADINFO* pTi=new THREADINFO;
361   FILEINFO* pfi=(FILEINFO*)g_object_get_data(G_OBJECT(g),"file");
362   pTi->pp.InitPingPong(sizeof(G4_FRAMEDATA)*50);
363   pTi->text=textview;
364   pTi->fCap=pfi->f;
365
366   stopButton=GTK_WIDGET(g_object_get_data(G_OBJECT(g),"stop_but"));
367   gtk_widget_set_sensitive(GTK_WIDGET(g),FALSE);
368   gtk_widget_set_sensitive(stopButton,TRUE);
369
370
371
372
373   gRunCont=1;
374   pthread_create(&contThread,NULL,ContThreadFxn,&pTi->pp);
375
376   g_timeout_add(4,(GSourceFunc)GetContData,pTi);
377   //g_idle_add((GSourceFunc)GetContData,pTi);
378
379
380
381
382 }
383
384
385 void OnStopCont(GtkWidget* w,gpointer g){
386
387   GtkWidget* start=GTK_WIDGET(g);
388   gRunCont=0;
389   pthread_join(contThread,NULL);
390
391   gtk_widget_set_sensitive(w,FALSE);
392   gtk_widget_set_sensitive(start,TRUE);
393
394 }
395
396 #include <unistd.h>
397 void* ContThreadFxn(void* p){
398
399   PingPong* pPP=(PingPong*)p;
400   struct timespec ts,tr;
401   G4_CMD_STRUCT cs;
402   int num_hubs;
403   G4_FRAMEDATA* fd;
404   int* hubList;
405   int actHubsRead;
406
407   cs.cmd=G4_CMD_GET_ACTIVE_HUBS;
408   cs.cds.id=G4_CREATE_ID(sysId,0,0);
409   cs.cds.action=G4_ACTION_GET;
410   cs.cds.pParam=NULL;
411   g4_set_query(&cs);
412
413
414   num_hubs=cs.cds.iParam;
415   if (num_hubs==0){
416     gRunCont=0;
417     return NULL;
418   }
419   hubList=new int[num_hubs];
420   cs.cds.pParam=hubList;
421   g4_set_query(&cs);
422
423
424   fd=new G4_FRAMEDATA[num_hubs];
425   int slRes;
426
427
428   while (gRunCont){
429     pthread_mutex_lock(&mutex);
430     actHubsRead=g4_get_frame_data(fd,sysId,hubList,num_hubs);
431     actHubsRead&=0xffff;    // just look at what's been read
432     if (actHubsRead)
433       pPP->WritePP((BYTE*)fd,sizeof(G4_FRAMEDATA)*actHubsRead);
434
435     pthread_mutex_unlock(&mutex);
436
437     ts.tv_sec=0;
438     ts.tv_nsec=4000000;
439     do {
440       slRes=nanosleep(&ts,&tr);
441       ts.tv_nsec=tr.tv_nsec;
442     }while(slRes==-1);
443
444   }
445
446   delete[] fd;
447   delete[] hubList;
448
449   return NULL;
450 }
451
452 gboolean GetContData(gpointer g){
453
454   THREADINFO* pTi=(THREADINFO*)g;
455   G4_FRAMEDATA fd[10];// max 10 hubs
456   int len;
457   int fd_size=sizeof(G4_FRAMEDATA);
458   int num_hubs;
459   if (gRunCont){
460     pthread_mutex_lock(&mutex);
461     do {
462       len=pTi->pp.ReadPP((BYTE*)fd);
463       if (len){
464     num_hubs=len/fd_size;
465     OutputData(pTi->text,fd,num_hubs,pTi->fCap);
466       }
467     }while (len);
468     pthread_mutex_unlock(&mutex);
469   }
470
471   return gRunCont?TRUE:FALSE;
472 }
473
474 void OnBoresight(GtkWidget* w,gpointer g){
475
476   // set boresight to 0,0,0
477   int bore=(int)(long)g;
478   float boreAng[3]={0.0f,0.0f,0.0};
479   G4_CMD_STRUCT cs;
480
481   if (!gConnected)
482     return;
483   cs.cmd=G4_CMD_BORESIGHT;
484   cs.cds.id=G4_CREATE_ID(sysId,-1,0);
485   cs.cds.action=(bore==1)?G4_ACTION_SET:G4_ACTION_RESET;
486   cs.cds.iParam=G4_TYPE_EULER_DEGREE;
487   cs.cds.pParam=boreAng;
488   g4_set_query(&cs);
489
490 }
491
492 void OnRotate(GtkWidget*,gpointer){
493
494   float aer[3];
495   G4_CMD_STRUCT cs;
496   if (!gConnected)
497     return;
498
499
500   cs.cmd=G4_CMD_FOR_ROTATE;
501   cs.cds.id=G4_CREATE_ID(sysId,0,0);
502   cs.cds.action=G4_ACTION_GET;
503   cs.cds.iParam=G4_TYPE_EULER_DEGREE;
504   cs.cds.pParam=aer;
505   g4_set_query(&cs);
506
507   FrameDlg fdlg(FD_ROT,aer);
508   int resp=fdlg.present_dlg();
509   if (resp==GTK_RESPONSE_OK){
510     fdlg.GetData(aer);
511     cs.cds.action=G4_ACTION_SET;
512     g4_set_query(&cs);
513
514   }
515
516
517 }
518
519 void OnTranslate(GtkWidget* w,gpointer g){
520
521   float xyz[3];
522   G4_CMD_STRUCT cs;
523   if (!gConnected)
524     return;
525
526   cs.cmd=G4_CMD_FOR_TRANSLATE;
527   cs.cds.id=G4_CREATE_ID(sysId,0,0);
528   cs.cds.action=G4_ACTION_GET;
529   cs.cds.iParam=G4_TYPE_INCH;
530   cs.cds.pParam=xyz;
531   g4_set_query(&cs);
532
533   FrameDlg dlg(FD_TRANS,xyz);
534   int resp=dlg.present_dlg();
535   if (resp==GTK_RESPONSE_OK){
536     dlg.GetData(xyz);
537     cs.cds.action=G4_ACTION_SET;
538     g4_set_query(&cs);
539   }
540
541
542 }
543
544 void OnFilter(GtkWidget*,gpointer){
545
546   G4_CMD_STRUCT cs;
547   float filt[2][4];
548
549   if (!gConnected)
550     return;
551
552   // get current values and fill dialog
553   cs.cmd=G4_CMD_FILTER;
554   cs.cds.id=G4_CREATE_ID(sysId,0,0);// using hub 0 to fill dialog
555   cs.cds.action=G4_ACTION_GET;
556   cs.cds.iParam=G4_DATA_POS;
557   cs.cds.pParam=filt[0];
558   g4_set_query(&cs);
559
560   cs.cds.iParam=G4_DATA_ORI;
561   cs.cds.pParam=filt[1];
562   g4_set_query(&cs);
563
564   FilterDlg dlg(filt[0],filt[1]);
565   int resp=dlg.present_dlg();
566
567   if (resp==GTK_RESPONSE_OK){
568     dlg.GetFilterData(filt[0],filt[1]);
569     cs.cds.id=G4_CREATE_ID(sysId,-1,0);        // set for all hubs
570     cs.cds.action=G4_ACTION_SET;
571     g4_set_query(&cs);
572
573     cs.cds.iParam=G4_DATA_POS;
574     cs.cds.pParam=filt[0];
575     g4_set_query(&cs);
576   }
577
578 }
579
580 void OnIncr(GtkWidget* w,gpointer g){
581
582   float incr[2];
583   G4_CMD_STRUCT cs;
584
585   cs.cmd=G4_CMD_INCREMENT;
586   cs.cds.id=G4_CREATE_ID(sysId,-1,0);
587   cs.cds.action=G4_ACTION_GET;
588   cs.cds.iParam=G4_TYPE_INCH<<16|G4_TYPE_EULER_DEGREE;
589   cs.cds.pParam=incr;
590
591   g4_set_query(&cs);
592
593   IncrDlg dlg(incr[0],incr[1]);
594   int rv=dlg.present_dlg();
595   if (rv==GTK_RESPONSE_OK){
596     dlg.get_increments(incr[0],incr[1]);
597     cs.cds.action=G4_ACTION_SET;
598     g4_set_query(&cs);
599   }
600
601 }
602
603
604 void OnUnits(GtkWidget* w,gpointer g){
605
606   G4_CMD_STRUCT cs;
607   int p_unit,o_unit;
608   cs.cmd=G4_CMD_UNITS;
609   cs.cds.id=G4_CREATE_ID(sysId,0,0);    // system wide
610   cs.cds.action=G4_ACTION_GET;
611   cs.cds.iParam=G4_DATA_POS;
612   cs.cds.pParam=&p_unit;
613   g4_set_query(&cs);
614
615   cs.cds.iParam=G4_DATA_ORI;
616   cs.cds.pParam=&o_unit;
617   g4_set_query(&cs);
618
619   UnitsDlg dlg(p_unit,o_unit);
620   int resp=dlg.present_dlg();
621   if (resp==GTK_RESPONSE_OK){
622     dlg.GetUnits(p_unit,o_unit);
623     cs.cds.action=G4_ACTION_SET;
624     g4_set_query(&cs);
625     cs.cds.iParam=G4_DATA_POS;
626     cs.cds.pParam=&p_unit;
627     g4_set_query(&cs);
628     isQuats=o_unit==G4_TYPE_QUATERNION?1:0;
629   }
630
631
632 }
633
634
635
636 void OnAbout(GtkWidget* w,gpointer g){
637
638   const gchar* authors[]={"James C. Farr, Polhemus Inc.",NULL};
639
640   gtk_show_about_dialog(GTK_WINDOW(g),"authors",authors,"comments",piterm_comment,"copyright","Copyright © Polhemus 2009-2013","program-name","G4Term","version",piterm_version,
641               "website","http://www.polhemus.com/",NULL);
642
643 }
644
645
646 void OnCapture(GtkWidget* w,gpointer g){
647
648   GtkWidget* dlg;
649   FILEINFO* pfi=(FILEINFO*)g;
650   gchar* filename;
651   int resp;
652
653   if (pfi->f){
654     dlg=gtk_message_dialog_new(NULL,GTK_DIALOG_MODAL,GTK_MESSAGE_QUESTION,GTK_BUTTONS_YES_NO,
655                "Data is presently being captured to %s.\n Would you like to stop capturing now?",
656                pfi->filename);
657     resp=gtk_dialog_run(GTK_DIALOG(dlg));
658     gtk_widget_destroy(dlg);
659     if (resp==GTK_RESPONSE_YES){
660       fclose(pfi->f);
661       pfi->f=NULL;
662     }
663   }
664   else {
665     dlg=gtk_file_chooser_dialog_new("Select a Capture File",NULL,GTK_FILE_CHOOSER_ACTION_SAVE,
666                     GTK_STOCK_SAVE,GTK_RESPONSE_ACCEPT,GTK_STOCK_CANCEL,
667                     GTK_RESPONSE_CANCEL,NULL);
668     resp=gtk_dialog_run(GTK_DIALOG(dlg));
669     if (resp==GTK_RESPONSE_ACCEPT){
670       filename=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg));
671       strcpy(pfi->filename,filename);
672       g_free(filename);
673       pfi->f=fopen(pfi->filename,"a");
674     }
675     gtk_widget_destroy(dlg);
676
677   }
678
679 }
680
681 void OnClose(GtkWidget* w,gpointer g){
682
683     if (gConnected)
684         g4_close_tracker();
685
686     gtk_main_quit();
687
688 }