From http://www.jwz.org/xscreensaver/xscreensaver-5.36.tar.gz
[xscreensaver] / android / screenhack-android.c
1 /* xscreensaver, Copyright (c) 2016 Jamie Zawinski <jwz@jwz.org>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  *
11  * Utility functions related to the hacks/ APIs.
12  */
13
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <time.h>
17 #include <sys/time.h>
18 #include <sys/utsname.h>
19 #include <android/log.h>
20 #include "screenhackI.h"
21 #include "xlockmoreI.h"
22 #include "textclient.h"
23
24 #if defined(USE_IPHONE) || (HAVE_ANDROID)
25 # include "jwzgles.h"
26 #else
27 # include <OpenGL/OpenGL.h>
28 #endif
29
30 #ifndef isupper
31 # define isupper(c)  ((c) >= 'A' && (c) <= 'Z')
32 #endif
33 #ifndef _tolower
34 # define _tolower(c)  ((c) - 'A' + 'a')
35 #endif
36
37 Bool 
38 get_boolean_resource (Display *dpy, char *res_name, char *res_class)
39 {
40   char *tmp, buf [100];
41   char *s = get_string_resource (dpy, res_name, res_class);
42   char *os = s;
43   if (! s) return 0;
44   for (tmp = buf; *s; s++)
45     *tmp++ = isupper (*s) ? _tolower (*s) : *s;
46   *tmp = 0;
47   free (os);
48
49   while (*buf &&
50          (buf[strlen(buf)-1] == ' ' ||
51           buf[strlen(buf)-1] == '\t'))
52     buf[strlen(buf)-1] = 0;
53
54   if (!strcmp (buf, "on") || !strcmp (buf, "true") || !strcmp (buf, "yes"))
55     return 1;
56   if (!strcmp (buf,"off") || !strcmp (buf, "false") || !strcmp (buf,"no"))
57     return 0;
58   fprintf (stderr, "%s: %s must be boolean, not %s.\n",
59            progname, res_name, buf);
60   return 0;
61 }
62
63 int 
64 get_integer_resource (Display *dpy, char *res_name, char *res_class)
65 {
66   int val;
67   char c, *s = get_string_resource (dpy, res_name, res_class);
68   char *ss = s;
69   if (!s) return 0;
70
71   while (*ss && *ss <= ' ') ss++;                       /* skip whitespace */
72
73   if (ss[0] == '0' && (ss[1] == 'x' || ss[1] == 'X'))   /* 0x: parse as hex */
74     {
75       if (1 == sscanf (ss+2, "%x %c", (unsigned int *) &val, &c))
76         {
77           free (s);
78           return val;
79         }
80     }
81   else                                                  /* else parse as dec */
82     {
83       /* Allow integer values to end in ".0". */
84       int L = strlen(ss);
85       if (L > 2 && ss[L-2] == '.' && ss[L-1] == '0')
86         ss[L-2] = 0;
87
88       if (1 == sscanf (ss, "%d %c", &val, &c))
89         {
90           free (s);
91           return val;
92         }
93     }
94
95   fprintf (stderr, "%s: %s must be an integer, not %s.\n",
96            progname, res_name, s);
97   free (s);
98   return 0;
99 }
100
101 double
102 get_float_resource (Display *dpy, char *res_name, char *res_class)
103 {
104   double val;
105   char c, *s = get_string_resource (dpy, res_name, res_class);
106   if (! s) return 0.0;
107   if (1 == sscanf (s, " %lf %c", &val, &c))
108     {
109       free (s);
110       return val;
111     }
112   fprintf (stderr, "%s: %s must be a float, not %s.\n",
113            progname, res_name, s);
114   free (s);
115   return 0.0;
116 }
117
118
119 char *
120 textclient_mobile_date_string (void)
121 {
122   struct utsname uts;
123   if (uname (&uts) < 0)
124     return strdup("uname() failed");
125   else
126     {
127       time_t now = time ((time_t *) 0);
128       char *ts = ctime (&now);
129       char *buf, *s;
130       if ((s = strchr(uts.nodename, '.')))
131         *s = 0;
132       buf = (char *) malloc(strlen(uts.machine) +
133                             strlen(uts.sysname) +
134                             strlen(uts.release) +
135                             strlen(ts) + 10);
136       sprintf (buf, "%s %s %s\n%s", uts.machine, uts.sysname, uts.release, ts);
137       return buf;
138     }
139 }
140
141
142 /* used by the OpenGL screen savers
143  */
144
145 /* Does nothing - prepareContext already did the work.
146  */
147 void
148 glXMakeCurrent (Display *dpy, Window window, GLXContext context)
149 {
150 }
151
152
153 /* clear away any lingering error codes */
154 void
155 clear_gl_error (void)
156 {
157   while (glGetError() != GL_NO_ERROR)
158     ;
159 }
160
161
162 // needs to be implemented in Android...
163 /* Copy the back buffer to the front buffer.
164  */
165 void
166 glXSwapBuffers (Display *dpy, Window window)
167 {
168 }
169
170
171 /* Called by OpenGL savers using the XLockmore API.
172  */
173 GLXContext *
174 init_GL (ModeInfo *mi)
175 {
176   // Window win = mi->window;
177
178   // Caller expects a pointer to an opaque struct...  which it dereferences.
179   // Don't ask me, it's historical...
180   static int blort = -1;
181   return (void *) &blort;
182 }
183
184 /* report a GL error. */
185 void
186 check_gl_error (const char *type)
187 {
188   char buf[100];
189   GLenum i;
190   const char *e;
191   switch ((i = glGetError())) {
192     case GL_NO_ERROR: return;
193     case GL_INVALID_ENUM:          e = "invalid enum";      break;
194     case GL_INVALID_VALUE:         e = "invalid value";     break;
195     case GL_INVALID_OPERATION:     e = "invalid operation"; break;
196     case GL_STACK_OVERFLOW:        e = "stack overflow";    break;
197     case GL_STACK_UNDERFLOW:       e = "stack underflow";   break;
198     case GL_OUT_OF_MEMORY:         e = "out of memory";     break;
199 #ifdef GL_TABLE_TOO_LARGE_EXT
200     case GL_TABLE_TOO_LARGE_EXT:   e = "table too large";   break;
201 #endif
202 #ifdef GL_TEXTURE_TOO_LARGE_EXT
203     case GL_TEXTURE_TOO_LARGE_EXT: e = "texture too large"; break;
204 #endif
205     default:
206       e = buf; sprintf (buf, "unknown GL error %d", (int) i); break;
207   }
208   __android_log_write(ANDROID_LOG_ERROR, "xscreensaver", e);
209 }