1 // Copyright 2005-2019 The Mumble Developers. All rights reserved.
2 // Use of this source code is governed by a BSD-style license
3 // that can be found in the LICENSE file at the root of the
4 // Mumble source tree or at <https://www.mumble.info/LICENSE>.
5 
6 /*
7  * G15 Helper Daemon for Mac OS X.
8  */
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <time.h>
13 #include <CoreFoundation/CoreFoundation.h>
14 
15 #include "g15helper.h"
16 #include "lglcd.h"
17 
18 #define ERROR_SUCCESS 0
19 #define BOOL unsigned char
20 #define BYTE unsigned char
21 #define TRUE 1
22 #define FALSE 0
23 
ods(const char * fmt,va_list args)24 static void ods(const char *fmt, va_list args) {
25 	vfprintf(stderr, fmt, args);
26 }
27 
warn(const char * fmt,...)28 static void warn(const char *fmt, ...) {
29 	va_list args;
30 	va_start(args, fmt);
31 	ods(fmt, args);
32 	va_end(args);
33 }
34 
die(int err,const char * fmt,...)35 static void die(int err, const char *fmt, ...) {
36 	va_list args;
37 	va_start(args, fmt);
38 	ods(fmt, args);
39 	va_end(args);
40 	exit(err);
41 }
42 
main(int argc,char * argv[])43 int main(int argc, char *argv[]) {
44 	int dwErr;
45 	BOOL bDetect = FALSE;
46 	int i;
47 	lgLcdConnectContextEx conn;
48 	lgLcdOpenByTypeContext ctx;
49 	lgLcdBitmap160x43x1 bitmap;
50 
51 	if (argc > 1 && (strcmp(argv[1], "/detect") == 0)) {
52 		warn("Detect mode!");
53 		bDetect = TRUE;
54 	} else if (!(argc > 1) || (strcmp(argv[1], "/mumble") != 0)) {
55 		CFUserNotificationDisplayAlert(0, 0, NULL,  NULL, NULL, CFSTR("Nothing to see here"), CFSTR("This program is run by Mumble, and should not be started separately."), CFSTR("OK"), NULL, NULL, NULL);
56 		return 0;
57 	}
58 
59 	/*
60 	 * Clear and set up initial structures.
61 	 */
62 	memset(&conn, 0, sizeof(conn));
63 	memset(&ctx, 0, sizeof(ctx));
64 	memset(&bitmap, 0, sizeof(bitmap));
65 
66 	conn.appFriendlyName = G15_WIDGET_NAME;
67 	conn.isAutostartable = FALSE;
68 	conn.isPersistent = FALSE;
69 	conn.dwAppletCapabilitiesSupported =LGLCD_APPLET_CAP_BASIC | LGLCD_APPLET_CAP_BW;
70 	conn.connection = LGLCD_INVALID_CONNECTION;
71 
72 	/*
73 	 * Initialize and connect.
74 	 */
75 	dwErr = lgLcdInit();
76 	if (dwErr != ERROR_SUCCESS)
77 		die(G15_ERR_INIT, "Unable to initialize Logitech LCD library. (Error: %i)", dwErr);
78 
79 	dwErr = lgLcdConnectEx(&conn);
80 	if (dwErr != ERROR_SUCCESS)
81 		die(G15_ERR_CONNECT, "Unable to connect to Logitech LCD manager. (Error: %i)", dwErr);
82 
83 	ctx.connection = conn.connection;
84 	ctx.device = LGLCD_INVALID_DEVICE;
85 	ctx.deviceType =LGLCD_DEVICE_BW;
86 
87 	dwErr = lgLcdOpenByType(&ctx);
88 
89 	warn("That returned %d %d", dwErr, ERROR_SUCCESS);
90 
91 	if (bDetect)
92 		return (dwErr != ERROR_SUCCESS);
93 	else if (dwErr != ERROR_SUCCESS)
94 		die(G15_ERR_OPEN, "Unable to open device. (Error: %i)", dwErr);
95 
96 	/*
97 	 * Diplay buffer format.
98 	 */
99 	bitmap.hdr.Format = LGLCD_BMP_FORMAT_160x43x1;
100 
101 	/*
102 	 * Main drawing loop.
103 	 */
104 	while (1) {
105 		int ret;
106 		int remain = 0;
107 		BYTE bPriority;
108 
109 		ret = read(0, &bPriority, 1);
110 		if (ret == -1 || ret != 1)
111 			die(G15_ERR_READFILE, "Error while reading priority.");
112 
113 		do {
114 			ret = read(0, bitmap.pixels + remain, G15_MAX_FBMEM - remain);
115 			if (ret < 1)
116 				die(G15_ERR_READFILE, "Error while reading framebuffer. %d (%s)", ret, strerror(errno));
117 			remain += ret;
118 		} while (remain < G15_MAX_FBMEM);
119 
120 		dwErr = lgLcdUpdateBitmap(ctx.device, (const lgLcdBitmapHeader *) &bitmap, bPriority ? LGLCD_SYNC_UPDATE(LGLCD_PRIORITY_ALERT) : LGLCD_SYNC_UPDATE(LGLCD_PRIORITY_NORMAL));
121 		if (dwErr != ERROR_SUCCESS)
122 			warn("Unable to update bitmap for device #%i successfully. (Error: %i)", i, dwErr);
123 	}
124 
125 	/*
126 	 * Close device connections.
127 	 */
128 	dwErr = lgLcdClose(ctx.device);
129 	if (dwErr != ERROR_SUCCESS)
130 		die(G15_ERR_CLOSE, "Unable to close LCD device. (Error: %i)", dwErr);
131 
132 	/*
133 	 * Disconnect from LCD monitor.
134 	 */
135 	dwErr = lgLcdDisconnect(conn.connection);
136 	if (dwErr != ERROR_SUCCESS)
137 		die(G15_ERR_DISCONNECT, "Unable to disconnect from LCD manager. (Error: %i)", dwErr);
138 
139 	/*
140 	 * Deinitialize G15 library.
141 	 */
142 	dwErr = lgLcdDeInit();
143 	if (dwErr != ERROR_SUCCESS)
144 		die(G15_ERR_DEINIT, "Unable to deinitialize LCD library. (Error: %i)", dwErr);
145 
146 	warn("Terminated successfully.");
147 
148 	return 0;
149 }
150