Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ PATH_AUDIO ?= "./wav"

CFLAGS ?= -O3 -g
LDFLAGS ?= -g
CFLAGS += -Wall -Werror
CFLAGS += -Wall
CFLAGS += -DVERSION=\"$(VERSION)\"
CFLAGS += -DPATH_AUDIO=\"$(PATH_AUDIO)\"

Expand All @@ -22,9 +22,6 @@ else
OS := $(shell uname)
ifeq ($(OS), Darwin)
BIN := $(NAME)
PKG_CONFIG_PATH := "./mac/lib/pkgconfig"
LIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs alure openal)
CFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --cflags alure openal)
LDFLAGS += -framework ApplicationServices -framework OpenAL
SRC += scan-mac.c
else
Expand Down Expand Up @@ -60,7 +57,7 @@ dist:
rm -rf $(NAME)-$(VERSION)

rec: rec.c
gcc -Wall -Werror rec.c -o rec
gcc -Wall rec.c -o rec

clean:
$(RM) $(OBJS) $(BIN) core rec
Expand Down
76 changes: 43 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
Nostalgia bucklespring keyboard sound
=====================================
# Nostalgia bucklespring keyboard sound

Copyright 2016 Ico Doornekamp

Expand All @@ -21,8 +20,7 @@ ScrollLock twice (but be aware that those ScrollLock events _are_ delivered to
the application); same to unmute. The keycode for muting can be changed with
the `-m` option. Use keycode 0 to disable the mute function.

Installation
------------
## Installation

[![Packaging status](https://repology.org/badge/tiny-repos/bucklespring.svg)](https://repology.org/project/bucklespring/versions)

Expand Down Expand Up @@ -64,21 +62,25 @@ To compile on debian-based linux distributions, first make sure the require
libraries and header files are installed, then simply run `make`:

#### Dependencies on Debian

```
$ sudo apt-get install libopenal-dev libalure-dev libxtst-dev pkg-config
```

#### Dependencies on Arch Linux

```
$ sudo pacman -S openal alure libxtst
```

#### Dependencies on Fedora Linux

```
$ sudo dnf install gcc openal-soft-devel alure-devel libX11-devel libXtst-devel
```

#### Building

```
$ make
$ ./buckle
Expand All @@ -103,28 +105,40 @@ $ bucklespring.buckle
The snap includes the OpenAL configuration tweaks mentioned in this README.
See http://snapcraft.io/ for more info about Snap packages


### MacOS

I've heard rumours that bucklespring also runs on MacOS. I've been told that
the following should do:
Bucklespring builds and runs on macOS without any external dependencies. The ALURE library dependency has been removed and replaced with a built-in WAV file loader.

```
$ brew install alure pkg-config
$ git clone https://github.com/zevv/bucklespring.git && cd bucklespring
$ sed -i '' 's/-Wall -Werror/-Wall/' Makefile
$ make
$ ./buckle
```

Note that you need superuser privileges to create the event tap on Mac OS X.
Also give your terminal Accessibility rights: system preferences -> security -> privacy -> accessibility
**System Requirements:**

- macOS with built-in OpenAL framework (included since macOS 10.4)
- No additional package installation required

**Permissions:**

- You need superuser privileges to create the event tap on macOS
- Grant your terminal Accessibility rights: System Preferences → Security & Privacy → Accessibility

**Usage:**

```
$ sudo ./buckle
```

If you want to use buckle while doing normal work, add an & behind the command:

If you want to use buckle while doing normal work, add an & behind the command.
```
$ sudo ./buckle &
```

**Note:** The build may show deprecation warnings for OpenAL functions since macOS 10.15, as Apple recommends AVAudioEngine for new applications. However, OpenAL continues to work perfectly for existing applications like bucklespring.

### Windows

I think the windows build is currently broken, it seems that switching from
Expand All @@ -135,11 +149,9 @@ called from another thread in the key capture callback, but my knowledge of the
win32 platform is so poor I'm not even able to run a debugger to see what is
happening. Help from an expert is much appreciated.

## Usage

Usage
-----

````
```
usage: ./buckle [options]

options:
Expand All @@ -154,36 +166,34 @@ options:
-p PATH load .wav files from directory PATH
-s WIDTH set stereo width [0..100]
-v increase verbosity / debugging
````

OpenAL notes
------------
```

## OpenAL notes

Bucklespring uses the OpenAL library for mixing samples and providing a
realistic 3D audio playback. This section contains some tips and tricks for
properly tuning OpenAL for bucklespring.

* The default OpenAL settings can cause a slight delay in playback. Edit or create
- The default OpenAL settings can cause a slight delay in playback. Edit or create
the OpenAL configuration file `~/.alsoftrc` and add the following options:

````
period_size = 32
periods = 4
````
```
period_size = 32
periods = 4
```

* If you are using headphones, enabling the head-related-transfer functions in OpenAL
- If you are using headphones, enabling the head-related-transfer functions in OpenAL
for a better 3D sound:

````
hrtf = true
````
```
hrtf = true
```

* When starting an OpenAL application, the internal sound card is selected for output,
- When starting an OpenAL application, the internal sound card is selected for output,
and you might not be able to change the device using pavucontrol. The option to select
an alternate device is present, but choosing the device has no effect. To solve this,
add the following option to the OpenAL configuration file:

````
allow-moves = true
````
```
allow-moves = true
```
87 changes: 82 additions & 5 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@

#ifdef __APPLE__
#include <OpenAL/al.h>
#include <OpenAL/alure.h>
#include <OpenAL/alc.h>
#else
#include <AL/al.h>
#include <AL/alure.h>
#include <AL/alc.h>
#endif

#include "buckle.h"
Expand All @@ -36,6 +36,10 @@ static void usage(char *exe);
static void list_devices(void);
static double find_key_loc(int code);

/* Simple WAV file loader to replace ALURE functionality */
static ALuint load_wav_file(const char *filename);
static const char* get_audio_error_string(void);



/*
Expand Down Expand Up @@ -94,7 +98,80 @@ static const struct option long_opts[] = {
{ 0, 0, 0, 0 }
};

/* Simple WAV file loader implementation */
static ALuint load_wav_file(const char *filename) {
FILE *file = fopen(filename, "rb");
if (!file) {
return 0;
}

char header[44];
if (fread(header, 1, 44, file) != 44) {
fclose(file);
return 0;
}

// Basic WAV header validation
if (strncmp(header, "RIFF", 4) != 0 || strncmp(header + 8, "WAVE", 4) != 0) {
fclose(file);
return 0;
}

// Extract audio parameters from header
int channels = *(short*)(header + 22);
int sample_rate = *(int*)(header + 24);
int bits_per_sample = *(short*)(header + 34);
int data_size = *(int*)(header + 40);

// Only support 16-bit mono audio for simplicity
if (channels != 1 || bits_per_sample != 16) {
fclose(file);
return 0;
}

// Read audio data
char *data = malloc(data_size);
if (!data) {
fclose(file);
return 0;
}

if (fread(data, 1, data_size, file) != data_size) {
free(data);
fclose(file);
return 0;
}

fclose(file);

// Create OpenAL buffer
ALuint buffer;
alGenBuffers(1, &buffer);
alBufferData(buffer, AL_FORMAT_MONO16, data, data_size, sample_rate);

free(data);

ALenum error = alGetError();
if (error != AL_NO_ERROR) {
alDeleteBuffers(1, &buffer);
return 0;
}

return buffer;
}

static const char* get_audio_error_string(void) {
ALenum error = alGetError();
switch (error) {
case AL_NO_ERROR: return "No error";
case AL_INVALID_NAME: return "Invalid name";
case AL_INVALID_ENUM: return "Invalid enum";
case AL_INVALID_VALUE: return "Invalid value";
case AL_INVALID_OPERATION: return "Invalid operation";
case AL_OUT_OF_MEMORY: return "Out of memory";
default: return "Unknown error";
}
}

int main(int argc, char **argv)
{
Expand Down Expand Up @@ -341,14 +418,14 @@ int play(int code, int press)

printd("Loading audio file \"%s\"", fname);

buf[idx] = alureCreateBufferFromFile(fname);
buf[idx] = load_wav_file(fname);
if(buf[idx] == 0) {

if(opt_fallback_sound) {
snprintf(fname, sizeof(fname), "%s/%02x-%d.wav", opt_path_audio, 0x31, press);
buf[idx] = alureCreateBufferFromFile(fname);
buf[idx] = load_wav_file(fname);
} else {
fprintf(stderr, "Error opening audio file \"%s\": %s\n", fname, alureGetErrorString());
fprintf(stderr, "Error opening audio file \"%s\": %s\n", fname, get_audio_error_string());
}

if(buf[idx] == 0) {
Expand Down