1 /* Copyright (c) 1999 Wee Liang (wliang@tartarus.uwa.edu.au)
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program (see the file COPYING); if not, write to the
15 * Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
32 #include <sys/ioctl.h>
34 #include <sys/types.h>
36 #include <linux/videodev.h>
37 #include <linux/soundcard.h>
40 #include <X11/Xutil.h>
42 #include <X11/StringDefs.h>
43 #include <X11/keysym.h>
45 #include <X11/extensions/shape.h>
46 #include <X11/extensions/xf86dga.h>
47 #include <X11/extensions/xf86vmode.h>
49 #include "wmgeneral/wmgeneral.h"
50 #include "wmgeneral/misc.h"
51 #include "wmtv-master.xpm"
56 #define VERSION "0.6.5"
61 #define NTFB 0 /* On/SetTune/Off Button */
62 #define SCANLB 1 /* Scan Left Button */
63 #define SCANRB 2 /* Scan Right Button */
64 #define FULLSB 3 /* Full Screen Toggle Button */
79 #define OPTIONS "hvd:g:e:b:"
86 /* Global Variables */
88 int card_present
= FALSE
;
89 int ntfb_status
= SETOFF
;
90 char *maxpreset
= NULL
;
92 int mode_present
= FALSE
;
115 unsigned long ccrfreq
;
118 unsigned long offset
;
123 char *fullscreen
= NULL
;
125 char *cname
[MAXCHAN
];
126 char *wcname
[MAXCHAN
];
129 char *dev
= "/dev/video";
131 int wmtv_mask_width
= 64;
132 int wmtv_mask_height
= 64;
133 char wmtv_mask_bits
[64*64];
136 int but_pressed
= FALSE
;
137 int but_clicked
= FALSE
;
143 rckeys wmtv_keys
[] = {
144 { "freqnorm", &norm
},
145 { "source", &source
},
146 { "maxpreset", &maxpreset
},
148 { "fullscreen", &fullscreen
},
153 XWindowAttributes Winattr
;
156 XF86VidModeModeInfo
**modelines
, *fullscreenmode
= NULL
;
157 XF86VidModeModeLine scmode
;
159 struct video_capability vcap
;
160 struct video_buffer vfb
;
161 struct video_window vwin
;
162 struct video_window vswin
;
163 struct video_channel vchn
, vchns
;
164 struct video_picture vpic
;
165 struct video_tuner vtun
;
166 struct video_audio vaud
;
167 struct video_mbuf vmbuf
;
168 struct video_mmap vmmap
;
169 struct video_clip vclip
[2];
170 struct video_clip vclip2
[2];
173 /* Function prototypes */
179 void FineTuneUp(void);
180 void FineTuneDown(void);
185 void ButtonDown(int);
187 void MuteAudio(void);
188 void UnMuteAudio(void);
190 void VolumeDown(void);
191 void DrawPresetChan(int);
192 void DoFullScreen(void);
193 void GetFrameBuffer(void);
194 void RetScreen(void);
195 void GrabImage(void);
197 void ParseRCFile(const char *, rckeys
*);
198 void ParseRCFile2(const char *);
199 void WriteRCFile(const char *);
200 void InitConfig(void);
201 void InitPalette(void);
209 main(int argc
, char *argv
[])
214 static struct option long_options
[] = {
215 {"display", 1, 0, 'd'},
216 {"geometry", 1, 0, 'g'},
220 {"version", 0, 0, 'v'},
224 progname
= strdup(argv
[0]);
226 strncpy(cfile
, (char *)getenv("HOME"), sizeof(char)*128);
227 strcat(cfile
, "/.wmtvrc");
231 c
= getopt_long (argc
, argv
, OPTIONS
, long_options
, &opind
);
239 fprintf(stderr, "wmtv: option - %s", long_options[opind].name);
241 fprintf(stderr, " with arg %s", optarg);
246 display_name
= strdup(optarg
);
249 geometry
= strdup(optarg
);
252 exe
= strdup(optarg
);
256 fprintf(stderr
, "wmtv: option not implemented yet\n");
271 createXBMfromXPM (wmtv_mask_bits
, wmtv_master_xpm
,
272 wmtv_mask_width
, wmtv_mask_height
);
273 openXwindow (argc
, argv
, wmtv_master_xpm
, wmtv_mask_bits
,
274 wmtv_mask_width
, wmtv_mask_height
);
276 AddMouseRegion (NTFB
, 47, 48, 59, 59); /* On/SetTune/Off Button */
277 AddMouseRegion (SCANLB
, 23, 48, 35, 59); /* Left Preset/Scan Button */
278 AddMouseRegion (SCANRB
, 35, 48, 47, 59); /* Right Preset/Scan Button */
279 AddMouseRegion (FULLSB
, 5, 5, 59, 44); /* Toggle FullScreen */
284 while (XPending(display
))
286 XNextEvent(display
, &Event
);
287 switch (Event
.type
) {
292 XCloseDisplay(display
);
294 if (ioctl(tfd
, VIDIOCCAPTURE
, &ccapt
) < 0) {
295 perror("ioctl VIDIOCCAPTURE");
302 if ((Event
.xany
.window
== fmwin
) && fmode
) {
306 i
= CheckMouseRegion (Event
.xbutton
.x
, Event
.xbutton
.y
);
310 t_lc
= Event
.xbutton
.time
;
315 if (ntfb_status
== SETUNE
) {
316 switch (Event
.xbutton
.button
) {
319 while (timebutton
== 1)
320 if (isource
== TELEVISION
)
324 if (isource
== TELEVISION
)
334 if (ntfb_status
== SETUNE
) {
335 switch (Event
.xbutton
.button
) {
339 if (isource
== TELEVISION
)
343 if (isource
== TELEVISION
)
353 switch (Event
.xbutton
.button
) {
375 i
= CheckMouseRegion (Event
.xbutton
.x
, Event
.xbutton
.y
);
380 if (Event
.xbutton
.time
- t_lc
>= 900) {
386 if (ntfb_status
== SETOFF
) {
390 else if (ntfb_status
== SETON
) {
392 ntfb_status
= SETUNE
;
393 copyXPMArea(96, 79, 11, 7, 6, 50);
394 RedrawWindowXYWH(6, 50, 11, 7);
397 ntfb_status
= SETOFF
;
403 else if (ntfb_status
== SETUNE
) {
405 offset
= (rfreq
- ccrfreq
);
406 // fprintf(stderr, "wmtv: finetune offset = %ld\n", offset);
409 DrawPresetChan(cchannel
);
412 ntfb_status
= SETOFF
;
421 if (ntfb_status
== SETUNE
)
426 if (ntfb_status
== SETUNE
)
431 switch (Event
.xbutton
.button
) {
437 if (((Event
.xbutton
.time
- t_lc
) <= 500) && (abs(Event
.xbutton
.x
- x_lc
) <= 10) && (abs(Event
.xbutton
.y
- y_lc
) <= 10) )
439 if ((ntfb_status
== SETON
) || (ntfb_status
== SETUNE
)) {
441 ntfb_status
= SETOFF
;
448 if (pid == (pid_t) 0) {
449 execlp("xawtv", "xawtv", "&", (char *) 0);
452 else if (pid < (pid_t) 0) {
458 if (waitpid(pid, NULL, 0) < 0) {
470 t_lc
= Event
.xbutton
.time
;
471 x_lc
= Event
.xbutton
.x
;
472 y_lc
= Event
.xbutton
.y
;
483 if (((Event
.xbutton
.time
- t_lc
) <= 500) && (abs(Event
.xbutton
.x
- x_lc
) <= 10) && (abs(Event
.xbutton
.y
- y_lc
) <= 10) )
485 if ((ntfb_status
== SETON
) || (ntfb_status
== SETUNE
)) {
492 t_lc
= Event
.xbutton
.time
;
493 x_lc
= Event
.xbutton
.x
;
494 y_lc
= Event
.xbutton
.y
;
507 case VisibilityNotify
:
508 switch(Event
.xvisibility
.state
) {
509 case VisibilityFullyObscured
:
511 if (tfd
&& (ntfb_status
!= SETOFF
) && !fmode
) {
512 if (ioctl(tfd
, VIDIOCCAPTURE
, &ccapt
) < 0) {
513 perror("ioctl VIDIOCCAPTURE");
517 case VisibilityPartiallyObscured
:
519 if (tfd
&& (ntfb_status
!= SETOFF
) && !fmode
) {
520 if (ioctl(tfd
, VIDIOCCAPTURE
, &ccapt
) < 0) {
521 perror("ioctl VIDIOCCAPTURE");
525 case VisibilityUnobscured
:
527 if (tfd
&& (ntfb_status
!= SETOFF
) && !fmode
) {
528 if (ioctl(tfd
, VIDIOCCAPTURE
, &ccapt
) < 0) {
529 perror("ioctl VIDIOCCAPTURE");
537 if ((Event
.xany
.window
== fmwin
) && fmode
) {
538 switch(XKeycodeToKeysym(display
, Event
.xkey
.keycode
, 0)) {
540 if (isource
== TELEVISION
)
544 if (isource
== TELEVISION
)
548 if (isource
== TELEVISION
)
552 if (isource
== TELEVISION
)
581 /* ButtonDown function */
583 ButtonDown(int button
)
587 copyXPMArea(79, 100, 12, 11, 47, 48);
588 RedrawWindowXYWH (47, 48, 12, 11);
591 copyXPMArea(55, 100, 12, 11, 23, 48);
592 RedrawWindowXYWH(35, 48, 12, 11);
595 copyXPMArea(67, 100, 12, 11, 35, 48);
596 RedrawWindowXYWH(35, 48, 12, 11);
604 /* ButtonUp function */
610 copyXPMArea(79, 88, 12, 11, 47, 48);
611 RedrawWindowXYWH(47, 48, 12, 11);
614 copyXPMArea(55, 88, 12, 11, 23, 48);
615 RedrawWindowXYWH(23, 48, 12, 11);
618 copyXPMArea(67, 88, 12, 11, 35, 48);
619 RedrawWindowXYWH(35, 48, 12, 11);
637 XWindowAttributes winattr
;
639 if (!XGetWindowAttributes (display
, iconwin
, &winattr
)) {
640 fprintf(stderr
, "wmtv: error getting winattr of iconwin\n");
643 if (!XTranslateCoordinates(display
, iconwin
, winattr
.root
,
644 -winattr
.border_width
,
645 -winattr
.border_width
,
646 &rx
, &ry
, &junkwin
)) {
647 fprintf(stderr
, "wmtv: error translating coordinates\n");
662 vclip
[0].x
= 0; /* Clipping Rect 1 */
665 vclip
[0].height
= 39;
666 vclip
[1].x
= 59; /* Clipping Rect 2 */
669 vclip
[1].height
= 39;
674 vchn
.channel
= tvsource
;
675 vaud
.audio
= tvsource
;
680 isource
= TELEVISION
;
681 else if (*p
== 'C') {
685 compchannel
= atoi(p
);
692 if (ioctl(tfd
, VIDIOCGTUNER
, &vtun
) < 0)
693 perror("ioctl VIDIOCGTUNER");
694 if (vtun
.flags
& VIDEO_TUNER_LOW
)
700 if (ioctl(tfd
, VIDIOCGCHAN
, &vchn
) < 0)
701 perror("ioctl VIDIOCGCHAN");
703 if (vchn
.flags
& VIDEO_VC_AUDIO
) {
704 if (ioctl(tfd
, VIDIOCGAUDIO
, &vaud
) < 0)
705 perror("ioctl VIDIOCGAUDIO");
708 if (vaud
.flags
& VIDEO_AUDIO_MUTE
) {
709 vaud
.flags
&= ~VIDEO_AUDIO_MUTE
; /* Unmute */
710 vaud
.volume
= (0xFFFF/2)+1;
713 if (isource
== TELEVISION
) {
714 for (i
=0; i
< CHAN_ENTRIES
; i
++) {
715 if (!strcmp(cname
[cchannel
], tvtuner
[i
].name
)) {
716 rfreq
= ((tvtuner
[i
].freq
[freqnorm
] / 1000) * st
) + ftune
[cchannel
];
717 ccrfreq
= rfreq
- ftune
[cchannel
];
721 DrawPresetChan(cchannel
);
723 else if (isource
== COMPOSITE
) {
724 DrawPresetChan(compchannel
);
726 else if (isource
== SVIDEO
) {
730 if (vchn
.flags
& VIDEO_VC_AUDIO
) {
731 if (ioctl(tfd
, VIDIOCSAUDIO
, &vaud
) < 0)
732 perror("ioctl VIDIOCSAUDIO");
736 if (ioctl(tfd
, VIDIOCSCHAN
, &vchn
) < 0)
737 perror("ioctl VIDIOCSCHAN");
740 if (ioctl(tfd
, VIDIOCSFREQ
, &rfreq
) < 0)
741 perror("ioctl VIDIOCSFREQ");
744 if (ioctl(tfd
, VIDIOCSWIN
, &vwin
) < 0)
745 perror("ioctl VIDIOCSWIN");
747 if (ioctl(tfd
, VIDIOCCAPTURE
, &ccapt
) < 0)
748 perror("ioctl VIDIOCCAPTURE");
758 if (ioctl(tfd
, VIDIOCCAPTURE
, &ccapt
) < 0)
759 perror("ioctl VIDIOCCAPTURE");
761 vaud
.audio
= tvsource
;
763 vaud
.flags
|= VIDEO_AUDIO_MUTE
;
765 if (vchn
.flags
& VIDEO_VC_AUDIO
) {
766 if (ioctl(tfd
, VIDIOCSAUDIO
, &vaud
) < 0)
767 perror("ioctl VIDIOCSAUDIO");
771 copyXPMArea(66, 79, 11, 7, 6, 50);
772 RedrawWindowXYWH(6, 50, 11, 7);
776 /* VolumeUp function */
780 if(vchn
.flags
& VIDEO_VC_AUDIO
) {
781 if (vaud
.volume
<= 0xFFFF) {
782 vaud
.audio
= tvsource
;
783 vaud
.volume
+= (0xFFFF/10);
784 if (ioctl(tfd
, VIDIOCSAUDIO
, &vaud
) < 0)
785 perror("ioctl VIDIOCSAUDIO");
791 /* VoumeDown function */
795 if (vchn
.flags
& VIDEO_VC_AUDIO
) {
796 if (vaud
.volume
> 0) {
797 vaud
.audio
= tvsource
;
798 vaud
.volume
-= (0xFFFF/10);
799 if (ioctl(tfd
, VIDIOCSAUDIO
, &vaud
) < 0)
800 perror("ioctl VIDIOCSAUDIO");
805 /* MuteAudio function */
809 if (vchn
.flags
& VIDEO_VC_AUDIO
) {
810 vaud
.audio
= tvsource
;
812 vaud
.flags
|= VIDEO_AUDIO_MUTE
;
813 if (ioctl(tfd
, VIDIOCSAUDIO
, &vaud
) < 0)
814 perror("ioctl VIDIOCSAUDIO");
820 /* UnMuteAudio function */
824 if ((vchn
.flags
& VIDEO_VC_AUDIO
) && (vaud
.flags
& VIDEO_AUDIO_MUTE
)) {
825 vaud
.audio
= tvsource
;
826 // vaud.volume = (0xFFFF/2)+1;
827 vaud
.flags
&= ~VIDEO_AUDIO_MUTE
;
828 if (ioctl(tfd
, VIDIOCSAUDIO
, &vaud
) < 0)
829 perror("ioctl VIDIOCSAUDIO");
835 /* ScanUp function */
841 if (ioctl(tfd
, VIDIOCSFREQ
, &rfreq
) < 0) {
842 perror("ioctl VIDIOCSFREQ");
846 if (ioctl(tfd
, VIDIOCGTUNER
, &vtun
) < 0) {
847 perror("ioctl VIDIOCGTUNER");
849 if (vtun
.signal
== 0xFFFF) {
856 /* ScanDown function */
862 if (ioctl(tfd
, VIDIOCSFREQ
, &rfreq
) < 0) {
863 perror("ioctl VIDIOCSFREQ");
867 if (ioctl(tfd
, VIDIOCGTUNER
, &vtun
) < 0) {
868 perror("ioctl VIDIOCGTUNER");
870 if (vtun
.signal
== 0xFFFF) {
876 /* FineTuneUp function */
881 if (ioctl(tfd
, VIDIOCSFREQ
, &rfreq
) < 0) {
882 perror("ioctl VIDIOCSFREQ");
887 /* FineTuneDown function */
892 if (ioctl(tfd
, VIDIOCSFREQ
, &rfreq
) < 0) {
893 perror("ioctl VIDIOCSFREQ");
898 /* ChanUp function */
903 if (cchannel
!= maxpst
)
905 for (i
=0; i
< CHAN_ENTRIES
; i
++) {
906 if (!strcmp(cname
[cchannel
], tvtuner
[i
].name
)) {
907 rfreq
= ((tvtuner
[i
].freq
[freqnorm
] / 1000) * st
) + ftune
[cchannel
];
908 ccrfreq
= rfreq
- ftune
[cchannel
];
913 DrawPresetChan(cchannel
);
914 if (ioctl(tfd
, VIDIOCSFREQ
, &rfreq
) < 0)
915 perror("ioctl VIDIOCSFREQ");
919 /* ChanDown function */
926 for (i
=0; i
< CHAN_ENTRIES
; i
++) {
927 if (!strcmp(cname
[cchannel
], tvtuner
[i
].name
)) {
928 rfreq
= ((tvtuner
[i
].freq
[freqnorm
] / 1000) * st
) + ftune
[cchannel
];
929 ccrfreq
= rfreq
- ftune
[cchannel
];
934 DrawPresetChan(cchannel
);
935 if (ioctl(tfd
, VIDIOCSFREQ
, &rfreq
) < 0)
936 perror("ioctl VIDIOCSFREQ");
940 /* DrawPresetChan function */
942 DrawPresetChan(int cchannel
)
949 if (isource
== TELEVISION
) {
950 sprintf(temp
, "%02d", cchannel
);
953 copyXPMArea(66, 79, 5, 7, k
, 50);
959 copyXPMArea((*p
-'0')*6 + 1, 79, 5, 7, k
, 50);
966 else if (isource
== COMPOSITE
) {
967 copyXPMArea (109, 79, 5, 7, 6, 50);
968 copyXPMArea ((compchannel
*6) + 1, 79, 5, 7, 12, 50);
971 else if (isource
== SVIDEO
) {
972 copyXPMArea(116, 79, 11, 7, 6, 50);
975 RedrawWindowXYWH(6, 50, 11, 7);
979 /* ParseRCFile function */
981 ParseRCFile(const char *filename
, rckeys
*keys
)
985 char *tokens
= " =\t\n";
989 if ((fp
= fopen(filename
, "r")) == NULL
) {
990 fprintf(stderr
, "wmtv: %s\n", strerror(errno
));
995 while (fgets(temp
, 128, fp
)) {
999 q
= strtok(q
, tokens
);
1000 while (key
>= 0 && keys
[key
].label
) {
1001 if ((!strcmp(q
, keys
[key
].label
))) {
1002 p
= strtok(NULL
, tokens
);
1003 free(*keys
[key
].var
);
1004 *keys
[key
].var
= strdup(p
);
1015 /* ParseRCFile2 function */
1017 ParseRCFile2(const char *filename
)
1022 char *tokens
= " \t\n()";
1027 if ((fp
= fopen(filename
, "r")) == NULL
) {
1028 fprintf(stderr
, "wmtv: %s\n", strerror(errno
));
1033 while (fgets(temp
, 128, fp
)) {
1036 q
= strtok(q
, tokens
);
1038 cname
[i
] = (char *)malloc(sizeof(q
));
1039 strncpy(cname
[i
], q
, sizeof(q
));
1041 p
= strtok(NULL
, tokens
);
1045 ftune
[i
] = -1*atoi(p
);
1047 else if (*p
== '+') {
1058 wcname
[i
] = (char *)malloc(sizeof(cname
[i
])+sizeof(p
));
1059 wcname
[i
] = strdup(cname
[i
]);
1060 sprintf(tp
, " (%d) ", ftune
[i
]);
1061 strcat(wcname
[i
], tp
);
1065 if ((q
= strchr(q
, '[')) != NULL
) {
1074 /* WriteRCFile function */
1076 WriteRCFile(const char *filename
)
1081 char *tokens
= " \t\n()";
1085 if ((fp
= fopen(filename
, "r+")) == NULL
) {
1086 fprintf(stderr
, "wmtv: %s\n", strerror(errno
));
1091 while (fgets(temp
, 128, fp
)) {
1094 q
= strtok(temp
, tokens
);
1095 if ((q
= strchr(q
, '[')) != NULL
) {
1096 for (i
= 0; i
<= maxpst
; i
++) {
1097 // fprintf(stderr, "offset is %ld\n", offset);
1098 sprintf(tp
, " (%ld) ", offset
);
1099 strtok(wcname
[cchannel
], tokens
);
1100 strcat(wcname
[cchannel
], tp
);
1101 fputs(wcname
[i
], fp
);
1111 /* InitPalette function */
1115 if (ioctl(tfd
, VIDIOCGFBUF
, &vfb
) < 0) {
1116 perror ("ioctl VIDIOCGFBUF");
1119 if (vfb
.base
== NULL
) {
1120 fprintf(stderr
, "wmtv: no physical frame buffer access\n");
1125 if (ioctl(tfd
, VIDIOCGPICT
, &vpic
) < 0) {
1126 perror("ioctl VIDIOCGPICT");
1128 vpic
.depth
= vfb
.depth
;
1129 switch(vpic
.depth
) {
1131 vpic
.palette
= VIDEO_PALETTE_HI240
;
1134 vpic
.palette
= VIDEO_PALETTE_RGB555
;
1137 vpic
.palette
= VIDEO_PALETTE_RGB565
;
1140 vpic
.palette
= VIDEO_PALETTE_RGB24
;
1143 vpic
.palette
= VIDEO_PALETTE_RGB32
;
1146 fprintf(stderr
, "wmtv: unsupported depth %d\n", vpic
.depth
);
1149 if (ioctl(tfd
, VIDIOCSPICT
, &vpic
) < 0) {
1150 perror("ioctl VIDIOCSPICT");
1153 /* InitConfig function */
1160 strcpy(temp
, "/etc/wmtvrc");
1161 ParseRCFile(temp
, wmtv_keys
);
1164 strncpy(temp
, (char *)getenv("HOME"), (sizeof(char)*128));
1165 strcat(temp
, "/.wmtvrc");
1166 ParseRCFile(temp
, wmtv_keys
);
1170 fprintf(stderr
, "wmtv: error - config file not found\n");
1174 if (maxpreset
!= NULL
)
1175 maxpst
= atoi(maxpreset
) - 1;
1179 if ((tpst
) != atoi(maxpreset
)) {
1180 fprintf(stderr
, "wmtv: error - maxpreset value does not match total channel value\n");
1183 if ((tfd
= open(dev
, O_RDWR
)) < 0) {
1184 perror("open failed");
1186 card_present
= TRUE
;
1189 for (i
=0; i
< CHAN_NAMES
; i
++) {
1190 if (!strcmp(chan_names
[i
].cname
, norm
)) {
1191 freqnorm
= chan_names
[i
].cind
;
1195 if (freqnorm
== -1) {
1196 fprintf(stderr
, "wmtv: error - set freqnorm in config file\n");
1200 if (ioctl(tfd
, VIDIOCGCAP
, &vcap
) < 0) {
1201 perror("ioctl VIDIOCGCAP");
1204 if (!(vcap
.type
& VID_TYPE_SCALES
)) {
1205 fprintf(stderr
, "%s: video device does not support scalling\n", progname
);
1208 if (!(vcap
.type
& VID_TYPE_CLIPPING
)) {
1209 fprintf(stderr
, "%s: video device does not support clipping\n", progname
);
1213 fswidth
= atoi(strtok(fullscreen
, "x\n"));
1214 fsheight
= atoi(strtok(NULL
, "x\n"));
1222 for (i
=0; i
< vcap
.channels
; i
++) {
1224 if (ioctl(tfd
, VIDIOCGCHAN
, &vchn
) < 0) {
1225 perror("ioctl VIDIOCGCHAN");
1227 if (!strcmp(vchn
.name
, source
)) {
1234 tvsource
= vchn
.channel
;
1236 if ((ioctl(tfd
, VIDIOCSCHAN
, &vchn
)) < 0)
1237 perror("ioctl VIDIOCSCHAN");
1241 fprintf(stderr
, "wmtv: invalid source in config file\n");
1247 if (ioctl(tfd
, VIDIOCGTUNER
, &vtun
) < 0) {
1248 perror("ioctl VIDIOCGTUNER");
1251 if (!strcmp(mode
, "pal")) {
1252 if (vtun
.flags
& VIDEO_TUNER_PAL
) {
1253 vtun
.mode
= VIDEO_MODE_PAL
;
1254 if (ioctl(tfd
, VIDIOCSTUNER
, &vtun
) < 0) {
1255 perror("ioctl VIDIOCSTUNER");
1259 if (!strcmp(mode
, "ntsc")) {
1260 if (vtun
.flags
& VIDEO_TUNER_NTSC
) {
1261 vtun
.mode
= VIDEO_MODE_NTSC
;
1262 if (ioctl(tfd
, VIDIOCSTUNER
, &vtun
) < 0) {
1263 perror("ioctl VIDIOCSTUNER");
1267 if (!strcmp(mode
, "secam")) {
1268 if (vtun
.flags
& VIDEO_TUNER_SECAM
) {
1269 vtun
.mode
= VIDEO_MODE_SECAM
;
1270 if (ioctl(tfd
, VIDIOCSTUNER
, &vtun
) < 0) {
1271 perror("ioctl VIDIOCSTUNER");
1278 for (i
=0; i
< vcap
.audios
; i
++) {
1280 if (ioctl(tfd
, VIDIOCGAUDIO
, &vaud
) < 0) {
1281 perror("ioctl VIDIOCGAUDIO");
1283 if (!(vaud
.flags
& VIDEO_AUDIO_MUTE
)) {
1284 vaud
.flags
|= VIDEO_AUDIO_MUTE
;
1285 if (ioctl(tfd
, VIDIOCSAUDIO
, &vaud
) < 0) {
1286 perror("ioctl VIDIOCSAUDIO");
1291 if (ioctl(tfd
, VIDIOCGFBUF
, &vfb
) < 0) {
1292 perror("ioctl VIDIOCGFBUF");
1296 /* GetFrameBuffer function */
1298 GetFrameBuffer(void)
1300 void *baseaddr
= NULL
;
1301 int evbr
, erbr
, flr
= 0;
1302 int bankr
, memr
, depth
;
1304 int bytesperline
, bitsperpixel
;
1305 XPixmapFormatValues
*pf
;
1307 if (!XGetWindowAttributes(display
, DefaultRootWindow(display
), &Winattr
)) {
1308 fprintf(stderr
, "wmtv: error getting winattr of root\n");
1311 depth
= Winattr
.depth
;
1313 if (XF86DGAQueryExtension(display
, &evbr
, &erbr
)) {
1314 XF86DGAQueryDirectVideo(display
, XDefaultScreen(display
), &flr
);
1315 if (flr
& XF86DGADirectPresent
) {
1316 XF86DGAGetVideoLL(display
, XDefaultScreen(display
),
1317 (int *) &baseaddr
, &bytesperline
, &bankr
, &memr
);
1321 fprintf(stderr
, "wmtv: error - XF86DGA Extensions not available\n");
1326 pf
= XListPixmapFormats(display
, &n
);
1327 for (i
=0; i
< n
; i
++) {
1328 if (pf
[i
].depth
== depth
) {
1329 depth
= pf
[i
].bits_per_pixel
;
1334 bitsperpixel
= (depth
+7) & 0xf8; /* Taken from */
1335 bytesperline
= Winattr
.width
* bitsperpixel
/ 8; /* Gerd Knorr's xawtv */
1337 vfb
.base
= baseaddr
;
1338 vfb
.height
= Winattr
.height
;
1339 vfb
.width
= Winattr
.width
;
1340 vfb
.depth
= bitsperpixel
;
1341 vfb
.bytesperline
= bytesperline
;
1343 if (Winattr
.depth
== 15)
1346 if (ioctl(tfd
, VIDIOCSFBUF
, &vfb
) < 0) {
1347 perror("ioctl VIDIOCSFBUF");
1352 /* DoFullScreen function */
1359 unsigned long back_pix
, fore_pix
;
1360 unsigned int borderwidth
= 0;
1363 XSizeHints fmsizehints
;
1364 XWMHints fmxwmhints
;
1367 unsigned long valuemask
;
1369 XSetWindowAttributes fmWinattr
;
1370 XWindowAttributes fmwinattr
;
1374 if (ioctl (tfd
, VIDIOCCAPTURE
, &ccapt
) < 0) {
1375 perror("ioctl VIDIOCCAPTURE");
1380 fmsizehints
.width
= fswidth
;
1381 fmsizehints
.height
= fsheight
;
1382 fmsizehints
.max_width
= vcap
.maxwidth
;
1383 fmsizehints
.max_height
= vcap
.maxheight
;
1384 fmsizehints
.min_width
= fswidth
;
1385 fmsizehints
.min_height
= fsheight
;
1386 fmsizehints
.flags
= (USPosition
| USSize
| PSize
| PMinSize
| PMaxSize
);
1390 back_pix
= WhitePixel(display
, DefaultScreen(display
));
1391 fore_pix
= BlackPixel(display
, DefaultScreen(display
));
1393 fmwin
= XCreateWindow(display
, DefaultRootWindow(display
), fmsizehints
.x
,
1394 fmsizehints
.y
, fmsizehints
.width
, fmsizehints
.height
,
1395 borderwidth
, CopyFromParent
, InputOutput
,
1396 CopyFromParent
, valuemask
, &fmWinattr
);
1399 XSetWMNormalHints(display
, fmwin
, &fmsizehints
);
1401 gcm
= (GCForeground
| GCBackground
| GCGraphicsExposures
);
1402 gcv
.foreground
= fore_pix
;
1403 gcv
.background
= back_pix
;
1404 gcv
.graphics_exposures
= 0;
1406 fmGC
= XCreateGC(display
, DefaultRootWindow(display
), gcm
, &gcv
);
1408 XSelectInput(display
, fmwin
, ButtonPressMask
| ExposureMask
|
1409 ButtonReleaseMask
| PointerMotionMask
|
1410 StructureNotifyMask
| VisibilityChangeMask
| KeyPressMask
);
1412 fmxwmhints
.flags
= StateHint
;
1413 fmxwmhints
.initial_state
= NormalState
;
1415 XSetWMHints(display
, fmwin
, &fmxwmhints
);
1418 if (XF86VidModeQueryExtension(display
, &evbr
, &erbr
)) {
1422 fprintf(stderr
, "wmtv: xf86mode extension not present\n");
1423 fprintf(stderr
, " switch disabled\n");
1427 XMapWindow(display
, fmwin
);
1430 if (!XGetWindowAttributes(display
, fmwin
, &fmwinattr
)) {
1431 fprintf(stderr
, "wmtv: error getting winattr of fmwin\n");
1435 if (!XTranslateCoordinates(display
, fmwin
, DefaultRootWindow(display
),
1436 -fmwinattr
.border_width
,
1437 -fmwinattr
.border_width
,
1438 &rx
, &ry
, &junkwin
)) {
1439 fprintf(stderr
, "wmtv: error translating coordinates for fmwin");
1442 vswin
.width
= fswidth
;
1443 vswin
.height
= fsheight
;
1444 vswin
.x
= fmsizehints
.x
+ rx
;
1445 vswin
.y
= fmsizehints
.y
+ ry
;
1446 vswin
.clipcount
= 0;
1448 if (ioctl(tfd
, VIDIOCSWIN
, &vswin
) < 0) {
1449 perror("ioctl VIDIOCSWIN");
1453 if (ioctl(tfd
, VIDIOCCAPTURE
, &ccapt
) < 0) {
1454 perror("ioctl VIDIOCCAPTURE");
1459 XF86VidModeGetModeLine(display
, XDefaultScreen(display
), &dcret
, &scmode
);
1460 XF86VidModeGetAllModeLines(display
, XDefaultScreen(display
), &tml
, &modelines
);
1462 for (i
=0; i
< tml
; i
++) {
1463 if ((modelines
[i
]->hdisplay
== fswidth
) &&
1464 (modelines
[i
]->vdisplay
== fsheight
)) {
1465 fullscreenmode
= modelines
[i
];
1466 mode_present
= TRUE
;
1471 if (!mode_present
) {
1472 fprintf(stderr
, "wmtv: mode line for resolution %d x %d not found\n", vcap
.maxwidth
, vcap
.maxheight
);
1475 XRaiseWindow(display
, fmwin
);
1478 XF86VidModeSwitchToMode(display
, XDefaultScreen(display
), fullscreenmode
);
1479 XF86VidModeSetViewPort(display
, XDefaultScreen(display
), vswin
.x
, vswin
.y
);
1480 XGrabPointer(display
, fmwin
, True
, 0, GrabModeAsync
, GrabModeAsync
,
1481 fmwin
, None
, CurrentTime
);
1487 /* RetScreen function */
1492 XF86VidModeModeInfo
*scm
= NULL
;
1495 if (ioctl(tfd
, VIDIOCCAPTURE
, &ccapt
)) {
1496 perror("ioctl VIDIOCCAPTURE");
1500 for (i
= 0; i
< tml
; i
++) {
1501 if ((modelines
[i
]->hdisplay
== Winattr
.width
) &&
1502 (modelines
[i
]->vdisplay
==Winattr
.height
))
1506 scm
->dotclock
= dcret
;
1507 scm
->hdisplay
= scmode
.hdisplay
;
1508 scm
->hsyncstart
= scmode
.hsyncstart
;
1509 scm
->hsyncend
= scmode
.hsyncend
;
1510 scm
->htotal
= scmode
.htotal
;
1511 scm
->vdisplay
= scmode
.vdisplay
;
1512 scm
->vsyncstart
= scmode
.vsyncstart
;
1513 scm
->vsyncend
= scmode
.vsyncend
;
1514 scm
->vtotal
= scmode
.vtotal
;
1515 scm
->flags
= scmode
.flags
;
1517 scm->privsize = scmode.privsize;
1518 scm->private = scmode.private;
1521 XClearWindow(display
, fmwin
);
1522 XFreeGC(display
, fmGC
);
1523 XMapRaised(display
, fmwin
);
1524 XUnmapWindow(display
, fmwin
);
1525 XUngrabPointer(display
, CurrentTime
);
1528 XClearWindow(display
, fmwin
);
1529 XFreeGC(display
, fmGC
);
1530 XMapRaised(display
, fmwin
);
1531 XUnmapWindow(display
, fmwin
);
1534 if (vidmode
&& mode_present
) {
1535 XF86VidModeSwitchToMode(display
, XDefaultScreen(display
), scm
);
1539 mode_present
= FALSE
;
1542 if (ioctl(tfd
, VIDIOCSWIN
, &vwin
) < 0) {
1543 perror("ioctl VIDIOCSWIN");
1546 if (ioctl(tfd
, VIDIOCCAPTURE
, &ccapt
) < 0) {
1547 perror("ioctl VIDIOCCAPTURE");
1552 /* GrabImage function */
1558 /* Usage function */
1562 fprintf(stderr
, "\n");
1563 fprintf(stderr
, "wmtv v%s, Copyright (c) 1999 Wee Liang <wliang@tartarus.uwa.edu.au>\n", VERSION
);
1564 fprintf(stderr
, "usage: wmtv [%s]\n", OPTIONS
);
1565 fprintf(stderr
, " -d, --display <host:vs>\tsets display name\n");
1566 fprintf(stderr
, " -g, --geometry <{+-}XP{+-}YP>\tsets geometry\n");
1567 fprintf(stderr
, " -b, --bpp\t\t\tdisplay color depth\n");
1568 fprintf(stderr
, " -e, --exe <filename>\t\tprogram to execute\n");
1569 fprintf(stderr
, " -v, --version\t\t\tprints version information\n");
1570 fprintf(stderr
, " -h, --help\t\t\tprints this message\n");
1571 fprintf(stderr
, "\n");
1575 /* Version function */
1579 fprintf(stderr
, "wmtv version %s\n", VERSION
);