/* callbacks for Bt848 frame grabber driver Copyright (C) 1996,97 Marcus Metzler (mocm@thp.uni-koeln.de) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * callbacks.cc */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "globals.h" #include "callbacks.h" #include "TVscreen.h" #include "allwidgets.h" #include "snap.h" #include "sound.h" /* */ /* user answers */ /* */ void nandemo(Widget w, XtPointer client_data, XtPointer call_data) { int *kotae =(int *) client_data; XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data; switch(cbs->reason){ case XmCR_OK: *kotae= 1; break; case XmCR_CANCEL: *kotae= 0; break; default: return; } } /* */ /* write message */ /* */ void mess(char *msg, char *msg2=NULL) { char buff[1024]; ostrstream str(buff,1024); str << "XTV: " << msg; if (msg2) str << msg2; str << ends; if(Message && XtIsRealized(Message)) XtVaSetValues(Message,XmNvalue,buff,NULL); if(Message2 && XtIsRealized(Message2)) XtVaSetValues(Message2,XmNvalue,buff,NULL); } /* */ /* help messages */ /* */ void help_mess(Widget w, XtPointer client_data, XEvent *event,char *any=NULL) { int me=int(client_data); switch(me){ case TEXTMESS: mess("Input Channel Name"); break; case LISTMESS: mess("Choose Channel"); break; case NORMMESS: mess("Select TV Norm"); break; case INPUTMESS: mess("Select Input"); break; case TUNERMESS: mess("Use Tuner Input"); break; case COMP1MESS: mess("Use Composite 1 Input"); break; case COMP2MESS: mess("Use Composite 2 Input"); break; case SVHSMESS: mess("Use SVHS Input"); break; case BRIGHTMESS: mess("Adjust Brightness"); break; case COLORMESS: mess("Adjust Color"); break; case CONTRASTMESS: mess("Adjust Contrast"); break; case HUEMESS: mess("Adjust Hue"); break; case PALMESS: mess("Set TV-norm to PAL"); break; case SECAMMESS: mess("Set TV-norm to SECAM"); break; case NTSCMESS: mess("Set TV-norm to NTSC"); break; case DELAYMESS: mess("Adjust Screen Refresh Delay"); break; case FREQMESS: mess("Adjust Frequency"); break; case CHANMESS: mess("Change Channel"); break; case FINEMESS: mess("Fine Tuning"); break; case QUITMESS: mess("Quit Program"); break; case CLOSEMESS: mess("Close Window"); break; case CHANNELMESS: mess("Open Channel Window"); break; case ADDMESS: mess("Add Channel to List"); break; case LOADMESS: mess("Load Channel"); break; case SAVEMESS: mess("Save Channel"); break; case DELETEMESS: mess("Delete Channel"); break; case CHANUP: mess("Switch Channel up"); break; case CHANDOWN: mess("Switch Channel down"); break; case VOLMESS: mess("Adjust Volume"); break; case SEQMESS: mess("Changing Sequence Length"); break; } } /* */ /* get saved list filename */ /* */ get_xtvrc(char *path,unsigned size) { const char *home=getenv("HOME"); const char *file=".xtvrc"; strncpy(path,home,size); strncat(path,"/",size); strncat(path,file,size); } /* */ /* Help Callback with message */ /* */ #define MSG "XTvscreen Version 0.5.22\n No Help available" // still needs some work void help_cb(Widget w, XtPointer client_data, XtPointer call_data) { static Widget dial; if(!dial){ Arg args[5]; int n=0; XmString msg = XmStringCreateLtoR (MSG,XmFONTLIST_DEFAULT_TAG); XtSetArg (args[n],XmNmessageString,msg); n++; dial =XmCreateInformationDialog(toplevel,"help_dialog",args,n); } XtManageChild(dial); XtPopup(XtParent(dial),XtGrabNone); mess("There's no help"); } /* */ /* Callback for File Menu */ /* */ // just the Quit button void file_cb(Widget w, XtPointer client_data, XtPointer call_data) { int item_no=int(client_data); switch(item_no){ case 0: /* Quit */ mess("bye bye"); XtAppSetExitFlag(app_context); } } /* */ /* Set frequency for TV Tuner */ /* */ void new_freq(Widget w, XtPointer client_data, XtPointer call_data) { int fr,ch,fi; if(freq==w){ // new value is set directly via frequency XmScaleGetValue(w,&fr); fr=fr*16/100; ch=CountryList.freqtochan(fr); if (!ch) ch=200; fi=CountryList.freqtofine(fr); XtVaSetValues(chan,XtNvalue,ch,NULL); XtVaSetValues(fine,XtNvalue,fi,NULL); } if(chan==w){ // new value is set via channel selection XmScaleGetValue(w,&ch); fr=CountryList.cftofreq(ch,0); fi=0; XtVaSetValues(freq,XtNvalue,fr*100/16,NULL); XtVaSetValues(fine,XtNvalue,fi,NULL); } if(fine==w){ // new value is set using fine tuning XmScaleGetValue(chan,&ch); fr=CountryList.cftofreq(ch,0); XmScaleGetValue(fine,&fi); fr+=fi; XtVaSetValues(freq,XtNvalue,fr*100/16,NULL); } XtVaSetValues(screen,XtNfreq,fr,NULL); } /* */ /* Set Delay */ /* Set Brightness */ /* Set Color */ /* Set Hue */ /* Set Contrast */ /* */ void new_dbch(Widget w, XtPointer client_data, XtPointer call_data) { int call=(int)client_data; switch(call){ case 0: int delay; XmScaleGetValue(w,&delay); XtVaSetValues(screen,XtNdelay,delay,NULL); break; case 1: int bright; XmScaleGetValue(w,&bright); XtVaSetValues(screen,XtNbright,bright,NULL); break; case 2: int color; XmScaleGetValue(w,&color); XtVaSetValues(screen,XtNcol,color,NULL); break; case 3: int hue; XmScaleGetValue(w,&hue); XtVaSetValues(screen,XtNhue,hue,NULL); break; case 4: int contrast; XmScaleGetValue(w,&contrast); XtVaSetValues(screen,XtNcontrast,contrast,NULL); break; case 5: int vol; XmScaleGetValue(w,&vol); set_master_vol(vol); break; } } /* */ /* Set number of images per sequence */ /* */ void new_seq(Widget w, XtPointer client_data, XtPointer call_data) { int snum; XmScaleGetValue(w,&snum); app_data.seqnum=snum; } /* */ /* Options callback */ /* */ void opt_cb(Widget &w,Boolean DO) { if (DO) { XtPopup(OptW,XtGrabNone); } else if (OptW) { XtPopdown(OptW); } } /* */ /* Toggle Norm */ /* */ void norm_tog(Widget w, XtPointer client_data, XtPointer call) { int norm=int(client_data); XmToggleButtonCallbackStruct *state=(XmToggleButtonCallbackStruct *)call; if(state->set){ XtVaSetValues(screen,XtNnorm,norm,NULL); switch(norm){ case PAL: mess("New TV norm is PAL"); break; case NTSC: mess("New TV norm is NTSC"); break; case SECAM: mess("New TV norm is SECAM"); break; } } } /* */ /* Input selection Callback */ /* */ void input_sel(Widget w, XtPointer client_data, XtPointer call) { int j; static int col=0; int in= int(client_data); static Boolean set=FALSE; /* Get normal shadow color */ //there is probably an easier way, but this works if (!set){ int col1,col2,col3; XtVaGetValues(input1[1],XmNbottomShadowColor,&col1,NULL); XtVaGetValues(input1[2],XmNbottomShadowColor,&col2,NULL); XtVaGetValues(input1[3],XmNbottomShadowColor,&col3,NULL); if (col1==col2) col=col1; else if(col1==col3) col=col1; else col=col2; set=TRUE; } // check where the call is coming from and set shades and toggle buttons if(w==input2[in]){ XmToggleButtonCallbackStruct *state=(XmToggleButtonCallbackStruct *)call; if(state->set){ XtVaSetValues(screen,XtNinputSelect,in,NULL); for (j=0;j<4;j++){ XtVaSetValues(input1[j],XmNbottomShadowColor,col,NULL); } XtVaSetValues(input1[in],XmNbottomShadowColor, BlackPixel(XtDisplay(input1[in]), DefaultScreen(XtDisplay(input1[in]))),NULL); } } else { XmToggleButtonGadgetSetState(input2[in],True,True); XtVaSetValues(screen,XtNinputSelect,in,NULL); for (j=0;j<4;j++){ XtVaSetValues(input1[j],XmNbottomShadowColor,col,NULL); } XtVaSetValues(input1[in],XmNbottomShadowColor, BlackPixel(XtDisplay(input1[in]), DefaultScreen(XtDisplay(input1[in]))),NULL); } switch(in){ case TUNER: mess("Selected Tuner input"); break; case COMP1: mess("Selected Composite 1 input"); break; case COMP2: mess("Selected Composite 2 input"); break; case SVHS: mess("Selected S-VHS input"); break; } } /* */ /* Set Channel Color, Brightnes, */ /* Hue and Contrast */ /* */ set_cbhc(int c,int b,int h,int co) { Widget widget; XtVaSetValues(screen,XtNcol,c,XtNbright,b,XtNhue,h, XtNcontrast,co,NULL); if (widget =XtNameToWidget(conwid,"Color")) XmScaleSetValue(widget,c); if (widget =XtNameToWidget(conwid,"Bright")) XmScaleSetValue(widget,b); if (widget =XtNameToWidget(conwid,"Hue")) XmScaleSetValue(widget,h); if (widget =XtNameToWidget(conwid,"Contrast")) XmScaleSetValue(widget,co); } /* */ /* Set Channel Norm and Input */ /* */ set_ni(int n,int i) { XtVaSetValues(screen,XtNnorm,n,XtNinputSelect,i,NULL); input_sel(input1[i], (XtPointer) i, NULL); XmToggleButtonGadgetSetState(norm[n],True,True); } /* */ /* close popup by button */ /* */ // works on all popups void close(Widget w, XtPointer client_data, XtPointer call_data) { XtPopdown(Widget(client_data)); } /* */ /* channel up/down */ /* */ void chan_ud(Widget w, XtPointer client_data, XtPointer call_data) { channel *h=&head; int ud=int(client_data); int *pos_lst; int pos_cnt; int newp=0; if(XmListGetSelectedPos(list,&pos_lst,&pos_cnt)) { switch (ud){ case CHANDOWN: newp=pos_lst[0]+1; if(newp>h->count()) newp=1; break; case CHANUP: newp=pos_lst[0]-1; if(newp<1) newp=h->count(); break; } XtFree((char*)pos_lst); } XmListSelectPos(list,newp,True); } /* */ /* select from channel list */ /* */ void select(Widget w, XtPointer client_data, XtPointer call_data) { XmListCallbackStruct *cbs=(XmListCallbackStruct *)call_data; channel *h=&head; int fr,ch,fi; while (h->next && h->number != cbs->item_position) h=h->next; // which item? if(h->input == TUNER){ fr=h->frequency; // set frequency and channel ch=CountryList.freqtochan(fr); fi=CountryList.freqtofine(fr); XtVaSetValues(screen,XtNfreq,fr,NULL); XtVaSetValues(freq,XmNvalue,fr*100/16,NULL); XtVaSetValues(chan,XmNvalue,ch,NULL); XtVaSetValues(fine,XmNvalue,fi,NULL); } set_cbhc(h->color,h->brightness,h->hue,h->contrast); set_ni(h->norm,h->input); mess("Selected channel ",h->name); } /* */ /* delete item from channel list */ /* */ void delete_item(Widget w, XtPointer client_data, XtPointer call_data) { channel *h=&head; int *posl,poscnt,p; if(XmListGetSelectedPos(list,&posl,&poscnt)){ p=posl[0]; while (h->next && h->number != p) h=h->next; // which one is it? mess("Deleted channel ",h->name); h->~channel(); XmListDeletePos(list,p); free(posl); } } /* */ /* save channel list */ /* */ void save_xtv(Widget w, XtPointer client_data, XtPointer call_data) { char FILE[30]; channel *h; get_xtvrc(FILE,30); ofstream fout(FILE); fout << "#" << endl; fout << "# List of Channels for xtvscreen" << endl; fout << "#" << endl; h=&head; while(h->next){ h=h->next; fout << *h << endl; } mess ("Saving channel list"); } /* */ /* load channel list */ /* */ void load_xtv(Widget w, XtPointer client_data, XtPointer call_data) { char FILE[30]; channel *h; channel *n; Boolean add; get_xtvrc(FILE,30); ifstream fin(FILE); while(fin.ignore(1000, '*')!=NULL){ n= new channel(&head,0,"empty",DCOL,DBRI,DHUE,DCONTRAST,DNORM,DIN); fin >> *n; h=&head; add=TRUE; while(h->next){ h=h->next; // do we already have that frequency ? if(!strcmp(h->name,n->name) && n!=h){ n->~channel(); add=FALSE; mess("Can't load existing channel:",h->name); } } if(add){ XmString str=XmStringCreateLocalized(h->name); XmListAddItemUnselected(list,str,0); XmStringFree(str); } } int fr,in; XtVaGetValues(screen,XtNfreq,&fr,XtNinputSelect,&in,NULL); h=&head; // if there is no default frequency // use first item of the list if (!fr && h->next){ int ch,fi; h=h->next; if(h->input == TUNER){ fr=h->frequency; ch=CountryList.freqtochan(fr); fi=CountryList.freqtofine(fr); XtVaSetValues(screen,XtNfreq,fr,NULL); XtVaSetValues(freq,XmNvalue,fr*100/16,NULL); XtVaSetValues(chan,XmNvalue,ch,NULL); XtVaSetValues(fine,XmNvalue,fi,NULL); } set_cbhc(h->color,h->brightness,h->hue,h->contrast); set_ni(h->norm,in); } mess("Loading channel list "); } /* */ /* channel callback */ /* */ void chan_cb(Widget w, XtPointer client_data, XtPointer call_data) { channel *ch; int fr; char *name; int n=0,call; XmString str,*strlist; static Arg args[10]; int c,br,hu,co,no,in; call=int(client_data); XtManageChild(list); XtManageChild(rowcol); switch(call){ case 0: //popup channel list XtPopup(ChanW,XtGrabNone); break; case 1: // add new channel and popup list name=XmTextFieldGetString(text); if (!name || !*name){ XtFree(name); return; } channel *h=&head; Boolean add=TRUE; while(h->next){ h=h->next; if(!strcmp(h->name,name)) { add=FALSE; mess("This name is already in list: ",h->name); char q[255]; ostrstream str(q,255); str << "Do you want to overwrite channel " << name << "?" << ends; if(Nandeska(w,q)){ XtVaGetValues(screen,XtNcol,&c,XtNbright,&br,XtNhue,&hu, XtNcontrast,&co,XtNnorm,&no,XtNinputSelect,&in,XtNfreq,&fr, NULL); if(in != TUNER) fr=0; h->frequency=fr; h->color=c; h->brightness=br; h->hue=hu; h->contrast=co; h->norm=no; h->input=in; } } } if(add){ XtVaGetValues(screen,XtNcol,&c,XtNbright,&br,XtNhue,&hu, XtNcontrast,&co,XtNnorm,&no,XtNinputSelect,&in,XtNfreq,&fr, NULL); if(in != TUNER) fr=0; ch= new channel(&head,fr,name,c,br,hu,co,no,in); str=XmStringCreateLocalized(name); mess("Adding channel ",name); XtFree(name); XmListAddItemUnselected(list,str,0); XmStringFree(str); XmTextFieldSetString(text,""); } XtPopup(ChanW,XtGrabNone); break; } } /* */ /* PopdownCallback */ /* */ void popdown(Widget w, XtPointer client_data, XtPointer call_data) { XtVaSetValues(Widget(client_data),XmNset,False,NULL); } /* */ /* Popup Control Window */ /* */ void popcon(Widget &w,Boolean DO) { if (DO) { XtPopup(dialog,XtGrabNone); } else if (dialog) { XtPopdown(dialog); } } /* */ /* Callback for Start MenuButton */ /* */ void start_cb(Widget w, XtPointer client_data, XtPointer call_data) { int item_no=int(client_data); Boolean CAP,CON,ASP; static Boolean done=False; static Boolean done2=False; switch(item_no){ case 0: /* Capture on/off */ XtVaGetValues(screen,XtNcap,&CAP,NULL); XtVaSetValues(screen,XtNcap,!CAP,NULL); if (!CAP) mess("Capturing is on"); else mess("Capturing is off"); break; case 1: /* Control Window on/off */ XtVaGetValues(w,XmNset,&CON,NULL); XtManageChild(conwid); XtManageChild(chan); XtManageChild(Message2); XtManageChild(pane); popcon(w,CON); int n; XtVaGetValues(screen,XtNnorm,&n,NULL); XmToggleButtonGadgetSetState(norm[n],True,True); n=0; XtVaGetValues(screen,XtNinputSelect,&n,NULL); XmToggleButtonGadgetSetState(input2[n],True,True); if (!done) XtAddCallback(dialog,XmNpopdownCallback,popdown,XtPointer(w)); done=True; break; case 2: /* channel list on */ chan_cb(w,0,NULL); break; case 3: /* options on/off */ XtVaGetValues(w,XmNset,&CON,NULL); XtManageChild(OptF); opt_cb(w,CON); if (!done2) XtAddCallback(dialog,XmNpopdownCallback,popdown,XtPointer(w)); done2=True; break; case 4: /* fixed aspect ratio on/off */ XtVaGetValues(w,XmNset,&ASP,NULL); if (ASP) { int h; XtVaGetValues(toplevel,XtNheight,&h,NULL); app_data.aspect=app_data.dasp; XtVaSetValues(toplevel,XtNheight,h+4,NULL); } else app_data.aspect=NOASP; break; case 5: XtVaGetValues(screen,XtNcap,&CAP,NULL); if (CAP){ int nb; char nbr[5]; ostrstream o(nbr,5); nb=snapit(screen,app_data.snapname,app_data.full_screen); o << hex << setw(3) << setfill(int('0')) << nb << ends; mess("Made snapshot number:",nbr); } else mess ("Capturing is off"); break; case 6: XtVaGetValues(screen,XtNcap,&CAP,NULL); if (CAP){ int nb; char nbr[20]; ostrstream o(nbr,20); mess("Starting sequence"); nb=sequence(screen,app_data.sequname,app_data.seqnum); o << hex << setw(3) << setfill(int('0')) << nb; mess("Made sequence number:",nbr); } else mess ("Capturing is off"); break; default: break; } } /* */ /* Callback for Audio MenuButton */ /* */ void audio_cb(Widget w, XtPointer client_data, XtPointer call_data) { int item_no=int(client_data); switch(item_no){ case 0: case 1: case 2: case 3: case 4: XtVaSetValues(screen,XtNaudio,item_no,NULL); break; default: break; } } void sizecheck(Widget w, XtPointer client_data, XEvent *event, char *c) { XConfigureEvent *ce=(XConfigureEvent *) event; if (ce->type !=ConfigureNotify) return; if (app_data.aspect == NOASP) return; int xa,ya; int dw=0,dh=0; int ww=0,hw=0,we=0,he=0; XtVaGetValues(screen,XtNwidth,&ww,XtNheight,&hw,NULL); we=ce->width; he=ce->height; dw=we-ww; dh=he-hw; switch (app_data.aspect) { case A4_3: xa=4; ya=3; break; case A16_9: xa=16; ya=9; break; } if (he < ya*ww/xa){ XtVaSetValues(toplevel,XtNheight,ya*ww/xa+dh,NULL); }else if (he > ya*ww/xa){ XtVaSetValues(toplevel,XtNwidth,xa*hw/ya+dw,NULL); } }