diff --git a/Makefile b/Makefile index 055aae2..d7d4151 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,10 @@ dist: $(PACKAGE)-$(VERSION)/src/Panel/project.conf \ $(PACKAGE)-$(VERSION)/src/Panel/applets/keyboard.c \ $(PACKAGE)-$(VERSION)/src/Panel/applets/project.conf \ + $(PACKAGE)-$(VERSION)/src/Phone/Makefile \ + $(PACKAGE)-$(VERSION)/src/Phone/project.conf \ + $(PACKAGE)-$(VERSION)/src/Phone/plugins/pulseaudio.c \ + $(PACKAGE)-$(VERSION)/src/Phone/plugins/project.conf \ $(PACKAGE)-$(VERSION)/Makefile \ $(PACKAGE)-$(VERSION)/project.conf $(RM) -- $(PACKAGE)-$(VERSION) diff --git a/src/Makefile b/src/Makefile index a67894b..bc28735 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,4 @@ -SUBDIRS = Panel +SUBDIRS = Panel Phone all: subdirs diff --git a/src/Phone/Makefile b/src/Phone/Makefile new file mode 100644 index 0000000..54acbc3 --- /dev/null +++ b/src/Phone/Makefile @@ -0,0 +1,21 @@ +SUBDIRS = plugins + + +all: subdirs + +subdirs: + @for i in $(SUBDIRS); do (cd "$$i" && $(MAKE)) || exit; done + +clean: + @for i in $(SUBDIRS); do (cd "$$i" && $(MAKE) clean) || exit; done + +distclean: + @for i in $(SUBDIRS); do (cd "$$i" && $(MAKE) distclean) || exit; done + +install: + @for i in $(SUBDIRS); do (cd "$$i" && $(MAKE) install) || exit; done + +uninstall: + @for i in $(SUBDIRS); do (cd "$$i" && $(MAKE) uninstall) || exit; done + +.PHONY: all subdirs clean distclean install uninstall diff --git a/src/Phone/plugins/Makefile b/src/Phone/plugins/Makefile new file mode 100644 index 0000000..cf777b4 --- /dev/null +++ b/src/Phone/plugins/Makefile @@ -0,0 +1,44 @@ +TARGETS = pulseaudio.so +PREFIX = /usr/local +DESTDIR = +LIBDIR = $(PREFIX)/lib +CC = cc +CPPFLAGSF= +CPPFLAGS= +CFLAGSF = -W `pkg-config --cflags libSystem gtk+-2.0` +CFLAGS = -Wall -g -O2 -pedantic -fPIC +AR = ar +RANLIB = ranlib +CCSHARED= $(CC) -shared +RM = rm -f +LN = ln -f +MKDIR = mkdir -m 0755 -p +INSTALL = install + + +all: $(TARGETS) + +pulseaudio_OBJS = pulseaudio.o +pulseaudio_CFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(CFLAGSF) $(CFLAGS) `pkg-config --cflags libpulse` +pulseaudio_LDFLAGS = $(LDFLAGSF) $(LDFLAGS) `pkg-config --libs libpulse` + +pulseaudio.so: $(pulseaudio_OBJS) + $(CCSHARED) -o pulseaudio.so $(pulseaudio_OBJS) $(pulseaudio_LDFLAGS) + +pulseaudio.o: pulseaudio.c + $(CC) $(pulseaudio_CFLAGS) -c pulseaudio.c + +clean: + $(RM) -- $(pulseaudio_OBJS) + +distclean: clean + $(RM) -- $(TARGETS) + +install: $(TARGETS) + $(MKDIR) $(DESTDIR)$(LIBDIR)/Phone/plugins + $(INSTALL) -m 0644 pulseaudio.so $(DESTDIR)$(LIBDIR)/Phone/plugins/pulseaudio.so + +uninstall: + $(RM) -- $(DESTDIR)$(LIBDIR)/Phone/plugins/pulseaudio.so + +.PHONY: all clean distclean install uninstall diff --git a/src/Phone/plugins/project.conf b/src/Phone/plugins/project.conf new file mode 100644 index 0000000..14e1323 --- /dev/null +++ b/src/Phone/plugins/project.conf @@ -0,0 +1,10 @@ +targets=pulseaudio +cflags_force=-W `pkg-config --cflags libSystem gtk+-2.0` +cflags=-Wall -g -O2 -pedantic -fPIC + +[pulseaudio] +type=plugin +sources=pulseaudio.c +cflags=`pkg-config --cflags libpulse` +ldflags=`pkg-config --libs libpulse` +install=$(LIBDIR)/Phone/plugins diff --git a/src/Phone/plugins/pulseaudio.c b/src/Phone/plugins/pulseaudio.c new file mode 100644 index 0000000..3683730 --- /dev/null +++ b/src/Phone/plugins/pulseaudio.c @@ -0,0 +1,164 @@ +/* $Id$ */ +/* Copyright (c) 2013-2014 Pierre Pronchery */ +/* This file is part of DeforaOS Desktop Phone */ +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ +/* TODO: + * - optionally loop the audio sample until told to stop + * - implement setting the volume (for headset/loudspeaker/audio...) */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#define max(a, b) ((a) > (b) ? (a) : (b)) + +#ifndef PACKAGE +# define PACKAGE "Phone" +#endif + + +/* Pulseaudio */ +/* private */ +/* types */ +typedef struct _PhonePlugin +{ + PhonePluginHelper * helper; + + guint source; + + pa_threaded_mainloop * pam; + pa_context * pac; + pa_operation * pao; +} Pulseaudio; + +/* prototypes */ +/* plug-in */ +static Pulseaudio * _pa_init(PhonePluginHelper * helper); +static void _pa_destroy(Pulseaudio * pa); +static int _pa_event(Pulseaudio * pa, PhoneEvent * event); + +/* useful */ +static void _pa_play(Pulseaudio * pa, char const * sound); + + +/* public */ +/* variables */ +PhonePluginDefinition plugin = +{ + "Pulseaudio", + "system-config-users", + NULL, + _pa_init, + _pa_destroy, + _pa_event, + NULL +}; + + +/* private */ +/* functions */ +/* pa_init */ +static Pulseaudio * _pa_init(PhonePluginHelper * helper) +{ + Pulseaudio * pa; + pa_mainloop_api * mapi = NULL; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + if((pa = object_new(sizeof(*pa))) == NULL) + return NULL; + pa->helper = helper; + pa->source = 0; + pa->pam = pa_threaded_mainloop_new(); + pa->pac = NULL; + pa->pao = NULL; + if(pa->pam == NULL) + { + _pa_destroy(pa); + error_set_code(1, "%s", "Could not initialize PulseAudio"); + return NULL; + } + mapi = pa_threaded_mainloop_get_api(pa->pam); + /* XXX update the context name */ + if((pa->pac = pa_context_new(mapi, PACKAGE)) == NULL) + { + _pa_destroy(pa); + error_set_code(1, "%s", "Could not initialize PulseAudio"); + return NULL; + } + pa_context_connect(pa->pac, NULL, 0, NULL); + pa_threaded_mainloop_start(pa->pam); + return pa; +} + + +/* pa_destroy */ +static void _pa_destroy(Pulseaudio * pa) +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + if(pa->source != 0) + g_source_remove(pa->source); + if(pa->pao != NULL) + pa_operation_cancel(pa->pao); + if(pa->pac != NULL) + pa_context_unref(pa->pac); + pa_threaded_mainloop_free(pa->pam); + object_delete(pa); +} + + +/* pa_event */ +static int _pa_event(Pulseaudio * pa, PhoneEvent * event) +{ + switch(event->type) + { + case PHONE_EVENT_TYPE_AUDIO_PLAY: + _pa_play(pa, event->audio_play.sample); + break; + case PHONE_EVENT_TYPE_AUDIO_STOP: + _pa_play(pa, NULL); + break; + default: /* not relevant */ + break; + } + return 0; +} + + +/* pa_play */ +static void _pa_play(Pulseaudio * pa, char const * sample) +{ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, sample); +#endif + if(sample == NULL) + { + /* cancel the current sample */ + if(pa->pao != NULL) + pa_operation_cancel(pa->pao); + pa->pao = NULL; + } + else if(pa->pao == NULL) + /* FIXME apply the proper volume */ + pa->pao = pa_context_play_sample(pa->pac, sample, NULL, + PA_VOLUME_NORM, NULL, NULL); +} diff --git a/src/Phone/project.conf b/src/Phone/project.conf new file mode 100644 index 0000000..fb8be74 --- /dev/null +++ b/src/Phone/project.conf @@ -0,0 +1,2 @@ +subdirs=plugins +dist=Makefile diff --git a/src/project.conf b/src/project.conf index e8f7173..a279657 100644 --- a/src/project.conf +++ b/src/project.conf @@ -1,2 +1,2 @@ -subdirs=Panel +subdirs=Panel,Phone dist=Makefile