Skip to content

Commit

Permalink
Merge branch 'cleanup'
Browse files Browse the repository at this point in the history
  • Loading branch information
toy committed Feb 1, 2017
2 parents 338f596 + bbebf73 commit e51bc0f
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 71 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/blueutil

/pkg/

build/
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CFLAGS = -Wall -Wextra -Werror -framework IOBluetooth

test: blueutil
./test

.PHONY: test
154 changes: 90 additions & 64 deletions blueutil.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#define VERSION "1.0.0"

#import <Foundation/Foundation.h>
#import <IOBluetooth/IOBluetooth.h>

// private methods
int IOBluetoothPreferencesAvailable();
Expand All @@ -22,92 +22,118 @@
void IOBluetoothPreferenceSetDiscoverableState(int state);

// dry
int BTSetParamState(int state, int (*getter)(), void (*setter)(int)) {
if (state == getter()) {
return EXIT_SUCCESS;
} else {
setter(state);

usleep(1000000); // Just wait, checking getter even in 10 seconds gives old result
return EXIT_SUCCESS;
int BTSetParamState(int state, int (*getter)(), void (*setter)(int), char *name) {
if (state == getter()) return true;

setter(state);

for (int i = 0; i < 101; i++) {
if (i) usleep(100000);
if (state == getter()) return true;
}

fprintf(stderr, "Failed to switch bluetooth %s %s in 10 seconds\n", name, state ? "on" : "off");
return false;
}

// short names
typedef int (*getterFunc)();
typedef int (*setterFunc)(int);
typedef bool (*setterFunc)(int);

#define BTAvaliable IOBluetoothPreferencesAvailable

#define BTPowerState IOBluetoothPreferenceGetControllerPowerState
int BTSetPowerState(int state) {
return BTSetParamState(state, BTPowerState, IOBluetoothPreferenceSetControllerPowerState);
bool BTSetPowerState(int state) {
return BTSetParamState(state, BTPowerState, IOBluetoothPreferenceSetControllerPowerState, "power");
}

#define BTDiscoverableState IOBluetoothPreferenceGetDiscoverableState
int BTSetDiscoverableState(int state) {
return BTSetParamState(state, BTDiscoverableState, IOBluetoothPreferenceSetDiscoverableState);
bool BTSetDiscoverableState(int state) {
return BTSetParamState(state, BTDiscoverableState, IOBluetoothPreferenceSetDiscoverableState, "discoverable state");
}

void printHelp() {
fprintf(stderr,
"blueutil v%s\n\n" \
"blueutil - show state\n" \
"blueutil power|discoverable - show state 1 or 0\n" \
"blueutil power|discoverable 1|0 - set state\n", VERSION);
#define io_puts(io, string) fputs (string"\n", io)

void printHelp(FILE *io) {
io_puts(io, "blueutil v"VERSION);
io_puts(io, "");
io_puts(io, "blueutil h[elp] - this help");
io_puts(io, "blueutil v[ersion] - show version");
io_puts(io, "");
io_puts(io, "blueutil - show state");
io_puts(io, "blueutil p[ower]|d[iscoverable] - show state 1 or 0");
io_puts(io, "blueutil p[ower]|d[iscoverable] 1|0 - set state");
io_puts(io, "");
io_puts(io, "Also original style arguments:");
io_puts(io, "blueutil s[tatus] - show status");
io_puts(io, "blueutil on - power on");
io_puts(io, "blueutil off - power off");
}

int main(int argc, const char * argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int result = EXIT_FAILURE;
#define is_abbr_arg(name, arg) (strncmp((name), (arg), strlen(arg) || 1) == 0)

int main(int argc, const char * argv[]) {
if (!BTAvaliable()) {
fprintf(stderr, "Error: Bluetooth not available!\n");
} else {
switch (argc) {
case 1: {
printf("Power: %d\nDiscoverable: %d\n", BTPowerState(), BTDiscoverableState());
result = EXIT_SUCCESS;
break;
io_puts(stderr, "Error: Bluetooth not available!");
return EXIT_FAILURE;
}
switch (argc) {
case 1: {
printf("Power: %d\nDiscoverable: %d\n", BTPowerState(), BTDiscoverableState());
return EXIT_SUCCESS;
}
case 2: {
if (is_abbr_arg("help", argv[1])) {
printHelp(stdout);
return EXIT_SUCCESS;
}
if (is_abbr_arg("version", argv[1])) {
io_puts(stdout, VERSION);
return EXIT_SUCCESS;
}
if (is_abbr_arg("status", argv[1])) {
printf("Status: %s\n", BTPowerState() ? "on" : "off");
return EXIT_SUCCESS;
}
if (strcmp("on", argv[1]) == 0) {
return BTSetPowerState(1) ? EXIT_SUCCESS : EXIT_FAILURE;
}
if (strcmp("off", argv[1]) == 0) {
return BTSetPowerState(0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
}
case 3: {
getterFunc getter = NULL;
setterFunc setter = NULL;

if (is_abbr_arg("power", argv[1])) {
getter = BTPowerState;
setter = BTSetPowerState;
} else if (is_abbr_arg("discoverable", argv[1])) {
getter = BTDiscoverableState;
setter = BTSetDiscoverableState;
} else {
printHelp(stderr);
return EXIT_FAILURE;
}
case 2:
case 3: {
getterFunc getter = NULL;
setterFunc setter = NULL;

if (strcmp("power", argv[1]) == 0) {
getter = BTPowerState;
setter = BTSetPowerState;
} else if (strcmp("discoverable", argv[1]) == 0) {
getter = BTDiscoverableState;
setter = BTSetDiscoverableState;
} else {
printHelp();
break;
}

if (argc == 2) {
printf("%d\n", getter());
result = EXIT_SUCCESS;
if (argc == 2) {
printf("%d\n", getter());
return EXIT_SUCCESS;
} else {
if (strcmp("1", argv[2]) == 0) {
return setter(1) ? EXIT_SUCCESS : EXIT_FAILURE;
} else if (strcmp("0", argv[2]) == 0) {
return setter(0) ? EXIT_SUCCESS : EXIT_FAILURE;
} else {
if (strcmp("1", argv[2]) == 0) {
result = setter(1);
} else if (strcmp("0", argv[2]) == 0) {
result = setter(0);
} else {
printHelp();
break;
}
printHelp(stderr);
return EXIT_FAILURE;
}
break;
}
default: {
printHelp();
break;
}
}
default: {
printHelp(stderr);
return EXIT_FAILURE;
}
}

[pool release];
return result;
}
6 changes: 0 additions & 6 deletions blueutil.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

/* Begin PBXBuildFile section */
8DD76F9A0486AA7600D96B5E /* blueutil.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* blueutil.m */; settings = {ATTRIBUTES = (); }; };
8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
B2A6DE1312F4624400C5007F /* IOBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B2A6DE1212F4624400C5007F /* IOBluetooth.framework */; };
/* End PBXBuildFile section */

Expand All @@ -26,7 +25,6 @@

/* Begin PBXFileReference section */
08FB7796FE84155DC02AAC07 /* blueutil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = blueutil.m; sourceTree = "<group>"; };
08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
32A70AAB03705E1F00C91783 /* blueutil_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blueutil_Prefix.pch; sourceTree = "<group>"; };
8DD76FA10486AA7600D96B5E /* blueutil */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = blueutil; sourceTree = BUILT_PRODUCTS_DIR; };
B2A6DE1212F4624400C5007F /* IOBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetooth.framework; path = System/Library/Frameworks/IOBluetooth.framework; sourceTree = SDKROOT; };
Expand All @@ -37,7 +35,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */,
B2A6DE1312F4624400C5007F /* IOBluetooth.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -67,7 +64,6 @@
08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
isa = PBXGroup;
children = (
08FB779EFE84155DC02AAC07 /* Foundation.framework */,
B2A6DE1212F4624400C5007F /* IOBluetooth.framework */,
);
name = "External Frameworks and Libraries";
Expand Down Expand Up @@ -170,7 +166,6 @@
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
PREBINDING = NO;
SDKROOT = macosx10.6;
};
name = Debug;
};
Expand All @@ -182,7 +177,6 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
SDKROOT = macosx10.6;
};
name = Release;
};
Expand Down
2 changes: 1 addition & 1 deletion blueutil_Prefix.pch
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
//

#ifdef __OBJC__
#import <Foundation/Foundation.h>
#import <IOBluetooth/IOBluetooth.h>
#endif
96 changes: 96 additions & 0 deletions test
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env bash

blueutil=./blueutil
errors=

status=$($blueutil)
trap "{
$blueutil power $($blueutil power)
$blueutil discoverable $($blueutil discoverable)
echo
if [[ -n \$errors ]]; then
echo -n \"\$errors\"
exit 1
fi
}" EXIT

ANSI_BOLD=$(tput bold 2> /dev/null)
ANSI_RED=$(tput setaf 1 2> /dev/null)
ANSI_GREEN=$(tput setaf 2 2> /dev/null)
ANSI_RESET=$(tput sgr0 2> /dev/null)

success() {
printf "$ANSI_GREEN"."$ANSI_RESET"
}

failure() {
printf "$ANSI_RED"F"$ANSI_RESET"
errors+="$@"$'\n'
}

assert_eq() {
[[ $1 == $2 ]] && success || failure "$ANSI_BOLD""$BASH_LINENO""$ANSI_RESET: Expected \"$1\" to eq \"$2\""
}

assert_match() {
[[ $1 =~ $2 ]] && success || failure "$ANSI_BOLD""$BASH_LINENO""$ANSI_RESET: Expected \"$1\" to match \"$2\""
}

# Init
$blueutil power 1
$blueutil discoverable 1
assert_eq "$($blueutil)" $'Power: 1\nDiscoverable: 1'
$blueutil power 0
$blueutil discoverable 0
assert_eq "$($blueutil)" $'Power: 0\nDiscoverable: 0'

# Power
$blueutil power 1
assert_eq "$($blueutil)" $'Power: 1\nDiscoverable: 0'

$blueutil power 0
assert_eq "$($blueutil)" $'Power: 0\nDiscoverable: 0'

# Power abbreviation
$blueutil p 1
assert_eq "$($blueutil)" $'Power: 1\nDiscoverable: 0'

$blueutil p 0
assert_eq "$($blueutil)" $'Power: 0\nDiscoverable: 0'

# Discoverable
$blueutil discoverable 1
assert_eq "$($blueutil)" $'Power: 0\nDiscoverable: 1'

$blueutil discoverable 0
assert_eq "$($blueutil)" $'Power: 0\nDiscoverable: 0'

# Discoverable abbreviation
$blueutil d 1
assert_eq "$($blueutil)" $'Power: 0\nDiscoverable: 1'

$blueutil d 0
assert_eq "$($blueutil)" $'Power: 0\nDiscoverable: 0'

# Status
assert_eq "$($blueutil status)" 'Status: off'
$blueutil power 1
assert_eq "$($blueutil status)" 'Status: on'
$blueutil power 0
assert_eq "$($blueutil status)" 'Status: off'

# On
$blueutil on
assert_eq "$($blueutil)" $'Power: 1\nDiscoverable: 0'

# Off
$blueutil off
assert_eq "$($blueutil)" $'Power: 0\nDiscoverable: 0'

# Help
assert_eq "$($blueutil help)" *'- this help'*
assert_eq "$($blueutil h)" *'- this help'*

# Version
assert_match "$($blueutil version)" '^[0-9]+\.[0-9]+\.[0-9]+$'
assert_match "$($blueutil v)" '^[0-9]+\.[0-9]+\.[0-9]+$'

0 comments on commit e51bc0f

Please sign in to comment.