Skip to content

Commit 9695965

Browse files
committed
Support windows build
1 parent fcbcef8 commit 9695965

File tree

3 files changed

+56
-22
lines changed

3 files changed

+56
-22
lines changed

README.md

+21-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ This is an unofficial Linux client for the Q2 Wi-Fi Internet Radio.
55
It uses libusb for the communication with the device in userspace.
66
This program provides some basic functionality for loading radio stations to each side of the radio.
77

8+
A [windows executable](https://github.com/vporpo/q2radio/releases) can be found in the releases. Please download the zip file containing the windows executable along with the dlls.
9+
810
## Requirements
911
* libusb: You need to have the libusb developers package (The header file libusb.h is required).
1012
* A c++ compiler
@@ -13,10 +15,26 @@ This program provides some basic functionality for loading radio stations to eac
1315
## Build Instructions
1416
```bash
1517
$ git clone https://github.com/vporpo/q2radio.git
16-
$ cd q2radio
17-
$ make
18-
$ sudo make install
18+
$ make -C q2radio/src
19+
$ sudo make install # or just run the binary: q2radio/src/q2radio
20+
```
21+
### Windows build (thanks to user @Untitled-Document-1)
22+
You can use [MSYS2 UCRT64](https://www.msys2.org/) as a build environment.
1923
```
24+
# In the MSYS2 UCRT64 terminal window:
25+
pacman -S git make mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-libusb
26+
git clone https://github.com/vporpo/q2radio.git
27+
make -C q2radio/src windows # Don't forget the 'windows' target
28+
# Run
29+
./q2radio/src/q2radio.exe
30+
```
31+
The chances are that you will get an error.
32+
33+
You need to make sure the Q2Radio device uses the WinUSB driver.
34+
There is a tool for changing the driver called [Zadig](https://zadig.akeo.ie) (check out the [libusb windows documentation](https://github.com/libusb/libusb/wiki/Windows#how-to-use-libusb-on-windows).
35+
In the Zadig tool click on Options > List All Devices. Then Q2Radio should show up as a "USB Serial Device" in the drop-down list.
36+
Switch it to the "WinUSB" driver by selecting it on the right hand side of the green arrow, and click on the "Replace Driver" button.
37+
Then try running `q2radio.exe` once again, this time it should work.
2038

2139
## Run examples:
2240
```bash

src/Makefile

+9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
all:
22
$(CXX) -O q2radio.cpp -lusb-1.0 -o q2radio
33

4+
windows:
5+
$(CXX) -O q2radio.cpp -lusb-1.0 -o q2radio -DWINDOWS
6+
7+
# For development use
8+
win_dst=q2radio_win
9+
windows_release: windows
10+
mkdir -p $(win_dst)
11+
zip -r $(win_dst).zip $(win_dst)/
12+
413
install:
514
cp q2radio /usr/local/bin/
615
clean:

src/q2radio.cpp

+26-19
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
// #define DBG(CMD) CMD
1717
#define DBG(CMD)
1818

19+
static constexpr const char *version = "0.1";
20+
1921
#include <assert.h>
2022
#include <getopt.h>
2123
#include <iomanip> // setfill(), setw()
@@ -146,7 +148,7 @@ struct Args {
146148
char *stationName = nullptr;
147149
char *stationUrl = nullptr;
148150
bool list = false;
149-
char *custom = nullptr;
151+
char *passthru = nullptr;
150152
char *ssid = nullptr;
151153
char *key = nullptr;
152154

@@ -178,9 +180,9 @@ struct Args {
178180
}
179181
std::cout << "\n";
180182
std::cout << "list: " << list << "\n";
181-
std::cout << "Custom: ";
182-
if (custom) {
183-
std::cout << custom;
183+
std::cout << "Passthru: ";
184+
if (passthru) {
185+
std::cout << passthru;
184186
}
185187
std::cout << "\n";
186188
std::cout << "SSID: \"";
@@ -203,7 +205,7 @@ static struct option long_options[] = {
203205
{"wifi-ssid", required_argument, 0, 'w'},
204206
{"wifi-key", required_argument, 0, 'k'},
205207
{"list", no_argument, 0, 'l'},
206-
{"custom", required_argument, 0, 'c'},
208+
{"passthru", required_argument, 0, 'c'},
207209
// WARNING: Keep "help" last for automatically generated usage() message
208210
{"help", no_argument, 0, 'h'}};
209211

@@ -231,10 +233,10 @@ void usage(char **argv) {
231233
}
232234
++i;
233235
}
234-
std::cerr << "Example: --side 0 --name \"Rebel State Radio\" --url "
235-
"\"http://eco.onestreaming.com:8142\"\n";
236-
std::cerr << "Example: --wifi-ssid \"<SSID>\" --wifi-key \"<WIFI KEY>\"\n";
237-
std::cerr << "Example: --custom \"gpre 0 name\":\n";
236+
std::cerr << "Example: --side 0 --name 'Rebel State Radio' --url 'http://eco.onestreaming.com:8142'\n";
237+
std::cerr << "Example: --wifi-ssid '<SSID>' --wifi-key '<WIFI KEY>'\n";
238+
std::cerr << "Example: --list (prints the stations on each side of the radio)\n";
239+
std::cerr << "Example: --passthru 'gpre 0 name' (passes raw commands directly to the radio - try 'help')\n";
238240
}
239241

240242
void parseArgs(int argc, char **argv, Args *args) {
@@ -267,7 +269,7 @@ void parseArgs(int argc, char **argv, Args *args) {
267269
args->list = true;
268270
return;
269271
case 'c':
270-
args->custom = (char *)optarg;
272+
args->passthru = (char *)optarg;
271273
break;
272274
case 'w':
273275
args->ssid = (char *)optarg;
@@ -307,9 +309,9 @@ void printResponse(libusb_device_handle *handle, bool out = true) {
307309
}
308310

309311
void banner(void) {
310-
std::cout << "+--------------- Q2 Radio Setup --------------+\n";
311-
std::cout << "| |\n";
312312
std::cout << "+---------------------------------------------+\n";
313+
std::cout << "| Q2 Radio Setup |\n";
314+
std::cout << "+------------------------------------- v" << version << " --+\n";
313315
}
314316

315317
int main(int argc, char **argv) {
@@ -319,31 +321,33 @@ int main(int argc, char **argv) {
319321
args.check();
320322
// args.dump();
321323

322-
libusb_device **devs; // list of devices
323324
libusb_context *ctx = NULL;
324325
int r;
325326
if ((r = libusb_init(&ctx)) < 0) {
326327
std::cerr << "libusb_init() error\n";
327328
exit(1);
328329
}
329330

330-
libusb_set_debug(ctx, 3);
331+
libusb_set_debug(ctx, 1);
332+
// libusb_device **devs; // list of devices
331333
// ssize_t dev_cnt;
332334
// if ((dev_cnt = libusb_get_device_list(ctx, &devs)) < 0) {
333335
// std::cerr << "libusb_get_device_list() error\n";
334336
// exit(1);
335337
// };
336338
// printAllDevs(devs, dev_cnt);
339+
// libusb_free_device_list(devs, 1);
337340

338341
libusb_device_handle *handle;
339342
int VID = 0x1f2e;
340343
int PID = 0x000a;
341344
if ((handle = libusb_open_device_with_vid_pid(ctx, VID, PID)) == NULL) {
342-
DBG(fprintf(stderr, "libusb_open_device_with_vid_pid(%04x:%04x)\n", VID,
345+
DBG(fprintf(stderr, "FAILED: libusb_open_device_with_vid_pid(%04x:%04x)\n", VID,
343346
PID));
347+
fprintf(stderr, "ERROR: Could not connect to the device!\n");
348+
fprintf(stderr, "Please make sure it is connected and turned on!\n");
344349
exit(1);
345350
}
346-
// libusb_free_device_list(devs, 1);
347351

348352
if (libusb_kernel_driver_active(handle, 0) == 1) {
349353
DBG(std::cerr << "Kernel driver active\n");
@@ -353,13 +357,16 @@ int main(int argc, char **argv) {
353357
}
354358

355359
int IF = 0;
356-
if (libusb_claim_interface(handle, IF) < 0) {
360+
#ifdef WINDOWS
361+
IF = 1;
362+
#endif
363+
if (libusb_claim_interface(handle, IF) != 0) {
357364
std::cerr << "libusb_claim_interface(" << IF << ") failed!\n";
358365
exit(1);
359366
}
360367

361-
if (args.custom) {
362-
sendStr(handle, args.custom);
368+
if (args.passthru) {
369+
sendStr(handle, args.passthru);
363370
printResponse(handle);
364371
return 0;
365372
}

0 commit comments

Comments
 (0)