Skip to content

Commit

Permalink
Refactor and rewrite.
Browse files Browse the repository at this point in the history
Perl script is removed in favour of C. Stale documentation and initfiles
are removed for now also.

C interface works, but still needs work (for example, mDNS is missing) -
see TODO.
  • Loading branch information
abrasive committed Apr 1, 2013
1 parent 98a8637 commit a2fb5d2
Show file tree
Hide file tree
Showing 26 changed files with 1,766 additions and 3,523 deletions.
4 changes: 0 additions & 4 deletions FreeBSD.notes

This file was deleted.

106 changes: 0 additions & 106 deletions INSTALL.md

This file was deleted.

42 changes: 4 additions & 38 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,40 +1,6 @@
SRCS := shairport.c rtsp.c common.c rtp.c player.c alac.c $(wildcard audio_*.c)

MY_CFLAGS= $(shell pkg-config --cflags ao)
MY_LDFLAGS= $(shell pkg-config --libs ao)
ifeq ($(shell uname),FreeBSD)
MY_LDFLAGS+= -lssl
else
MY_CFLAGS+= $(shell pkg-config --cflags openssl)
MY_LDFLAGS+= $(shell pkg-config --libs openssl)
endif

CFLAGS:=-O2 -Wall $(MY_CFLAGS)
LDFLAGS:=-lm -lpthread $(MY_LDFLAGS)

OBJS=socketlib.o shairport.o alac.o hairtunes.o
all: hairtunes shairport

hairtunes: hairtunes.c alac.o
$(CC) $(CFLAGS) -DHAIRTUNES_STANDALONE hairtunes.c alac.o -o $@ $(LDFLAGS)

shairport: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $@ $(LDFLAGS)

clean:
-@rm -rf hairtunes shairport $(OBJS)


%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@


prefix=/usr/local
install: hairtunes shairport
install -D -m 0755 hairtunes $(DESTDIR)$(prefix)/bin/hairtunes
install -D -m 0755 shairport.pl $(DESTDIR)$(prefix)/bin/shairport.pl
install -D -m 0755 shairport $(DESTDIR)$(prefix)/bin/shairport

.PHONY: all clean install

.SILENT: clean
LIBS := -lcrypto -lm -lao -lpthread

shairport: $(SRCS)
gcc -ggdb -Wall $(SRCS) $(LIBS) -o shairport
13 changes: 13 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
- make BUFFER_FRAMES adjustable
- use getopt
- copyright updates
- signal handlers
- pluggable audio drivers
- audio usage
- finish ao
- makefile
- documentation
- PKGBUILD, initscript, systemd, launchd plist
- mDNS
- volume control
- tidy debug printing
12 changes: 6 additions & 6 deletions alac.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static const int host_bigendian = 0;
struct {signed int x:24;} se_struct_24;
#define SignExtend24(val) (se_struct_24.x = val)

void allocate_buffers(alac_file *alac)
void alac_allocate_buffers(alac_file *alac)
{
alac->predicterror_buffer_a = malloc(alac->setinfo_max_samples_per_frame * 4);
alac->predicterror_buffer_b = malloc(alac->setinfo_max_samples_per_frame * 4);
Expand Down Expand Up @@ -110,7 +110,7 @@ void alac_set_info(alac_file *alac, char *inputbuffer)
if (!host_bigendian)
_Swap32(alac->setinfo_8a_rate);

allocate_buffers(alac);
alac_allocate_buffers(alac);

}

Expand Down Expand Up @@ -687,9 +687,9 @@ static void deinterlace_24(int32_t *buffer_a, int32_t *buffer_b,

}

void decode_frame(alac_file *alac,
unsigned char *inbuffer,
void *outbuffer, int *outputsize)
void alac_decode_frame(alac_file *alac,
unsigned char *inbuffer,
void *outbuffer, int *outputsize)
{
int channels;
int32_t outputsamples = alac->setinfo_max_samples_per_frame;
Expand Down Expand Up @@ -1104,7 +1104,7 @@ void decode_frame(alac_file *alac,
}
}

alac_file *create_alac(int samplesize, int numchannels)
alac_file *alac_create(int samplesize, int numchannels)
{
alac_file *newfile = malloc(sizeof(alac_file));

Expand Down
12 changes: 7 additions & 5 deletions alac.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#ifndef __ALAC__DECOMP_H
#define __ALAC__DECOMP_H

#include <stdint.h>

typedef struct alac_file alac_file;

alac_file *create_alac(int samplesize, int numchannels);
void decode_frame(alac_file *alac,
unsigned char *inbuffer,
void *outbuffer, int *outputsize);
alac_file *alac_create(int samplesize, int numchannels);
void alac_decode_frame(alac_file *alac,
unsigned char *inbuffer,
void *outbuffer, int *outputsize);
void alac_set_info(alac_file *alac, char *inputbuffer);
void allocate_buffers(alac_file *alac);
void alac_allocate_buffers(alac_file *alac);

struct alac_file
{
Expand Down
22 changes: 22 additions & 0 deletions audio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef _AUDIO_H
#define _AUDIO_H

typedef struct {
// start of program
int (*init)(int argc, char **argv);
// at end of program
void (*deinit)(void);

void (*start)(int sample_rate);
// block of samples
void (*play)(short buf[], int samples);
void (*stop)(void);

// may be NULL, in which case soft volume is applied
void (*volume)(double vol);
} audio_ops;

extern audio_ops audio_dummy;
extern audio_ops audio_ao;

#endif //_AUDIO_H
53 changes: 53 additions & 0 deletions audio_ao.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <stdio.h>
#include <unistd.h>
#include <memory.h>
#include <ao/ao.h>
#include "common.h"
#include "audio.h"

ao_device *dev = NULL;

static int init(int argc, char **argv) {
printf("ao: init\n");
ao_initialize();
ao_sample_format fmt;
memset(&fmt, 0, sizeof(fmt));

fmt.bits = 16;
fmt.rate = 44100;
fmt.channels = 2;
fmt.byte_format = AO_FMT_NATIVE;

int driver = ao_default_driver_id();

dev = ao_open_live(driver, &fmt, NULL);

return dev ? 0 : 1;
}

static void deinit(void) {
if (dev)
ao_close(dev);
}

static void start(int sample_rate) {
printf("ao: start\n");
if (sample_rate != 44100)
die("unexpceted sample rate!\n");
}

static void play(short buf[], int samples) {
ao_play(dev, (char*)buf, samples*4);
}

static void stop(void) {
}

audio_ops audio_ao = {
.init = &init,
.deinit = &deinit,
.start = &start,
.stop = &stop,
.play = &play,
.volume = NULL
};
52 changes: 52 additions & 0 deletions audio_dummy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include "audio.h"

int Fs;
long long starttime, samples_played;

static int dummy_init(int argc, char **argv) {
return 0;
}

static void dummy_deinit(void) {
}

static void dummy_start(int sample_rate) {
Fs = sample_rate;
starttime = 0;
samples_played = 0;
printf("dummy audio output started at Fs=%d Hz\n", sample_rate);
}

static void dummy_play(short buf[], int samples) {
struct timeval tv;

// this is all a bit expensive but it's long-term stable.
gettimeofday(&tv, NULL);

long long nowtime = tv.tv_usec + 1e6*tv.tv_sec;

if (!starttime)
starttime = nowtime;

samples_played += samples;

long long finishtime = starttime + samples_played * 1e6 / Fs;

usleep(finishtime - nowtime);
}

static void dummy_stop(void) {
printf("dummy audio stopped\n");
}

audio_ops audio_dummy = {
.init = &dummy_init,
.deinit = &dummy_deinit,
.start = &dummy_start,
.stop = &dummy_stop,
.play = &dummy_play,
.volume = NULL
};
Loading

0 comments on commit a2fb5d2

Please sign in to comment.