tone-player: Adds new tone playback APIs 29/231429/12 submit/tizen/20200512.012802
authorJaechul Lee <jcsing.lee@samsung.com>
Fri, 3 Apr 2020 00:32:53 +0000 (09:32 +0900)
committerJaechul Lee <jcsing.lee@samsung.com>
Wed, 6 May 2020 06:43:22 +0000 (15:43 +0900)
These new APIs will be used by capi-media-tone-player.

  server          : org.pulseaudio.Server
  object path     : /org/pulseaudio/TonePlayer
  interface       : org.pulseaudio.TonePlayer

  method name     : TonePlay
  method argument : [in] unsigned int for tone index
                    [in] signed int for duration
                    [in] signed int for client pid
                    [in] string for role
                    [in] signed int for parent id
                    [out] unsigned int for stream index
  return value    : None

  method name     : ToneStop
  method argument : [in] unsigned int for stream index
  return value    : None

[Version] 13.0.15
[Issue Type] Improvement

Change-Id: I090e917e26697250bb187b0d2df8cd6042875354
Signed-off-by: Jaechul Lee <jcsing.lee@samsung.com>
Makefile.am
packaging/pulseaudio-modules-tizen.spec
src/module-tone-player.c [new file with mode: 0644]
src/tones.h [new file with mode: 0644]

index 9cb257c..6023379 100644 (file)
@@ -37,6 +37,7 @@ pulsemodlibexec_LTLIBRARIES = \
                module-tizenaudio-source.la \
                module-tizenaudio-policy.la \
                module-sound-player.la \
+               module-tone-player.la \
                module-poweroff.la
 if ENABLE_HALTC
 pulsemodlibexec_LTLIBRARIES += \
@@ -74,6 +75,11 @@ module_sound_player_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_sound_player_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS)
 module_sound_player_la_CFLAGS = $(MODULE_CFLAGS) $(DBUS_CFLAGS)
 
+module_tone_player_la_SOURCES = src/module-tone-player.c
+module_tone_player_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_tone_player_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS)
+module_tone_player_la_CFLAGS = $(MODULE_CFLAGS) $(DBUS_CFLAGS)
+
 module_tizenaudio_policy_la_SOURCES = \
           src/module-tizenaudio-policy.c   \
           src/stream-manager.c   src/stream-manager.h   src/stream-manager-priv.h   \
index 0c13813..9a56089 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          13.0.14
+Version:          13.0.15
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
@@ -70,6 +70,7 @@ install -m 0644 %SOURCE1 %{buildroot}%{_tmpfilesdir}/pulseaudio.conf
 %license LICENSE.LGPL-2.1+
 %{_libdir}/pulse-13.0/modules/module-poweroff.so
 %{_libdir}/pulse-13.0/modules/module-sound-player.so
+%{_libdir}/pulse-13.0/modules/module-tone-player.so
 %{_libdir}/pulse-13.0/modules/module-tizenaudio-policy.so
 %{_libdir}/pulse-13.0/modules/module-tizenaudio-sink.so
 %{_libdir}/pulse-13.0/modules/module-tizenaudio-source.so
diff --git a/src/module-tone-player.c b/src/module-tone-player.c
new file mode 100644 (file)
index 0000000..f4a64c9
--- /dev/null
@@ -0,0 +1,527 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2020 Jaechul Lee <jcsing.lee@samsung.com>
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2.1 of the License,
+  or (at your option) any later version.
+
+  PulseAudio 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 Lesser General Public License
+  along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include "tones.h"
+
+#include <pulsecore/module.h>
+#include <pulsecore/log.h>
+#include <pulsecore/namereg.h>
+#include <pulsecore/sink.h>
+#include <pulsecore/modargs.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/core-error.h>
+
+#include <pulse/xmalloc.h>
+#include <pulse/proplist.h>
+#include <pulse/timeval.h>
+
+#ifdef HAVE_DBUS
+#include <pulsecore/dbus-shared.h>
+#include <pulsecore/protocol-dbus.h>
+#include <pulsecore/dbus-util.h>
+#endif
+
+PA_MODULE_AUTHOR("Jaechul Lee");
+PA_MODULE_DESCRIPTION("Tone Generator module");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(true);
+
+#define TONE_PLAYER_OBJECT_PATH                 "/org/pulseaudio/TonePlayer"
+#define TONE_PLAYER_INTERFACE                   "org.pulseaudio.TonePlayer"
+
+#define TONE_PLAYER_METHOD_NAME_TONE_PLAY       "TonePlay"
+#define TONE_PLAYER_METHOD_NAME_TONE_STOP       "ToneStop"
+
+#define TONE_SAMPLERATE             44100
+#define TONE_CHANNELS               1
+#define TONE_FORMAT                 2
+#define TONE_FRAMESIZE              (TONE_CHANNELS * TONE_FORMAT)
+
+/*
+ * Todo: reducing memory(lazy loading), set default rate,map for avoiding reample
+ */
+
+#if HAVE_DBUS
+struct userdata {
+    pa_module *module;
+    pa_dbus_connection *dbus_conn;
+};
+
+enum method_handler_index {
+    METHOD_HANDLER_TONE_PLAY,
+    METHOD_HANDLER_TONE_STOP,
+    METHOD_HANDLER_MAX
+};
+
+enum {
+    TONE_SOUND_MESSAGE_UNLINK = PA_SINK_INPUT_MESSAGE_MAX
+};
+
+struct tone_freq {
+    int16_t l_freq;
+    int16_t m_freq;
+    int16_t h_freq;
+    int16_t msec;
+    int16_t loop;
+    int16_t index;
+};
+
+struct tone {
+    struct tone_freq *info;
+    uint32_t num;
+    int32_t rbytes;
+
+    uint16_t index;
+    uint32_t bytes;
+    uint16_t loop;
+    uint32_t sample;
+    bool silence;
+};
+
+inline uint32_t tone_msec_to_bytes(uint16_t msec) {
+    uint32_t size;
+
+    size = TONE_SAMPLERATE * TONE_FRAMESIZE * msec / 1000;
+    if (size % TONE_FRAMESIZE)
+        size = PA_ROUND_DOWN(size, TONE_FRAMESIZE);
+
+    return size;
+}
+
+struct tone *tone_new(uint32_t index, int rbytes) {
+    struct tone *t = pa_xnew0(struct tone, 1);
+
+    t->info = (struct tone_freq *)pa_xmemdup(tones[index], sizeof(int16_t)*TONE_ELEMENTS);
+    t->rbytes = rbytes;
+    t->num = index;
+
+    t->silence = false;
+    t->loop = t->info[0].loop;
+    t->bytes = tone_msec_to_bytes(t->info[0].msec);
+
+    pa_log_info("tone created. index(%u), request_bytes(%d)", t->num, t->rbytes);
+
+    return t;
+}
+
+void tone_free(struct tone *t) {
+    if (!t)
+        return;
+
+    pa_xfree(t->info);
+    pa_xfree(t);
+
+    return 0;
+}
+
+int tone_peek_fixed_size(struct tone *t, pa_sink_input *si, pa_memchunk *chunk, uint32_t length) {
+    short *buf;
+    uint32_t i;
+    uint32_t size;
+    uint32_t quota = 0;
+    double amplitude, f1, f2, f3;
+    struct tone_freq* info = &(t->info[t->index]);
+
+    /* EOS */
+    if (t->rbytes != -1 && t->rbytes <= t->sample * TONE_FRAMESIZE)
+        return -1;
+
+    /* silence */
+    if (t->silence)
+        info->l_freq = info->m_freq = info->h_freq = 0;
+
+    t->bytes -= size = PA_MIN(t->bytes, length);
+
+    if (info->l_freq > 0) quota++;
+    if (info->m_freq > 0) quota++;
+    if (info->h_freq > 0) quota++;
+
+    chunk->index = 0;
+    chunk->length = size;
+    chunk->memblock = pa_memblock_new(si->core->mempool, chunk->length);
+    buf = (short *)pa_memblock_acquire(chunk->memblock);
+
+    for (i = 0; i < size / TONE_FRAMESIZE; i++) {
+        f1 = sin(2. * M_PI * info->l_freq * t->sample / TONE_SAMPLERATE);
+        f2 = sin(2. * M_PI * info->m_freq * t->sample / TONE_SAMPLERATE);
+        f3 = sin(2. * M_PI * info->h_freq * t->sample / TONE_SAMPLERATE);
+
+        if (quota > 0) {
+            amplitude = (f1 + f2 + f3) / quota;
+            amplitude *= 1.0;
+            amplitude *= 32767;
+        } else {
+            amplitude = 0.;
+        }
+        *(buf++) = (short)amplitude;
+        t->sample++;
+    }
+    pa_memblock_release(chunk->memblock);
+
+    /* calc index */
+    if (t->bytes == 0) {
+        if (info->loop > 0) {
+            info->loop -= 1;
+            t->index = info->index;
+            t->bytes = tone_msec_to_bytes(t->info[t->index].msec);
+            return 0;
+        }
+
+        /* check next item */
+        info += 1;
+        t->index += 1;
+
+        if (info->l_freq == -1 && info->m_freq == -1 && info->h_freq == -1) {
+            if (info->loop == 0) { /* infinite loop */
+                memcpy(t->info, tones[t->num], sizeof(uint16_t)*TONE_ELEMENTS);
+                t->index = info->index;
+            } else if (info->loop == 1) { /* last playback */
+                t->silence = true;
+                pa_log_debug("silence stream start");
+            } else { /* counting loops */
+                uint16_t tmp = info->loop - 1;
+                memcpy(t->info, tones[t->num], sizeof(uint16_t)*TONE_ELEMENTS);
+                t->info[t->index].loop = tmp;
+                t->index = info->index;
+            }
+        }
+        t->bytes = tone_msec_to_bytes(t->info[t->index].msec);
+    }
+
+    pa_log_debug("%hd,%hd,%hd %hd remain(%d), size(%u), index(%d)",
+                        info->l_freq, info->m_freq, info->h_freq, info->msec,
+                        t->bytes, size, t->index);
+
+    return 0;
+}
+
+static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+    struct tone *t = (struct tone *)i->userdata;
+
+    if (!t)
+        return -1;
+
+    if (tone_peek_fixed_size(t, i, chunk, length) < 0) {
+        if (pa_sink_input_safe_to_remove(i)) {
+            pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(i),
+                                TONE_SOUND_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
+        }
+        return -1;
+    }
+
+    chunk->length = PA_MIN(chunk->length, length);
+
+    return 0;
+}
+
+static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    struct tone *t = i->userdata;
+
+    if (!t)
+        return;
+}
+
+static void sink_input_kill_cb(pa_sink_input *i) {
+    struct tone *t = i->userdata;
+
+    tone_free(t);
+    pa_sink_input_unlink(i);
+    pa_sink_input_unref(i);
+}
+
+static int sink_input_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
+    pa_sink_input *i = PA_SINK_INPUT(o);
+
+    switch (code) {
+        case TONE_SOUND_MESSAGE_UNLINK:
+            pa_sink_input_kill(i);
+            break;
+    }
+
+    return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
+}
+
+static void handle_tone_play(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+    dbus_uint32_t result = -1;
+    struct userdata *u = (struct userdata *)userdata;
+
+    uint32_t index;
+    int32_t duration;
+    uint32_t client_pid;
+    const char *role;
+    uint32_t parent_id;
+
+    struct tone *t;
+    pa_sink_input *i;
+    pa_sample_spec ss;
+    pa_sink_input_new_data data;
+    int32_t request_bytes;
+    pa_proplist *p = NULL;
+
+    pa_assert(conn);
+    pa_assert(msg);
+    pa_assert(userdata);
+
+    pa_assert_se(dbus_message_get_args(msg, NULL,
+                                       DBUS_TYPE_UINT32, &index,
+                                       DBUS_TYPE_INT32, &duration,
+                                       DBUS_TYPE_INT32, &client_pid,
+                                       DBUS_TYPE_STRING, &role,
+                                       DBUS_TYPE_INT32, &parent_id,
+                                       DBUS_TYPE_INVALID));
+
+    pa_log_info("index(%u), duration(%d), pid(%d), role(%s), parent_id(%d)",
+            index, duration, client_pid, role, parent_id);
+
+    if (index >= sizeof(tones)/sizeof(uint16_t)/TONE_ELEMENTS) {
+        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s",
+                                    "org.tizen.multimedia.InvalidArgument");
+        goto exit;
+    }
+
+    p = pa_proplist_new();
+    pa_proplist_sets(p, PA_PROP_MEDIA_ROLE, role);
+    pa_proplist_setf(p, PA_PROP_APPLICATION_PROCESS_ID_ORIGIN, "%d", client_pid);
+    pa_proplist_setf(p, PA_PROP_MEDIA_PARENT_ID, "%d", parent_id);
+
+    ss.format = PA_SAMPLE_S16LE;
+    ss.rate = TONE_SAMPLERATE;
+    ss.channels = TONE_CHANNELS;
+
+    pa_sink_input_new_data_init(&data);
+    pa_sink_input_new_data_set_sink(&data, pa_namereg_get(u->module->core, NULL, PA_NAMEREG_SINK), false, true);
+    data.driver = __FILE__;
+    pa_sink_input_new_data_set_sample_spec(&data, &ss);
+    pa_sink_input_new_data_set_volume(&data, NULL);
+    pa_sink_input_new(&i, u->module->core, &data);
+    pa_sink_input_new_data_done(&data);
+
+    request_bytes = duration != -1 ? pa_usec_to_bytes(duration*PA_MSEC_PER_SEC, &ss) : -1;
+
+    t = tone_new(index, request_bytes);
+    if (!t) {
+        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s",
+                                    "org.tizen.multimedia.OutOfMemory");
+        goto exit;
+    }
+
+    i->userdata = t;
+    i->pop = sink_input_pop_cb;
+    i->kill = sink_input_kill_cb;
+    i->process_rewind = sink_input_process_rewind_cb;
+    i->parent.process_msg = sink_input_process_msg;
+
+    pa_sink_input_put(i);
+
+    result = (dbus_uint32_t)i->index;
+
+    pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &result);
+
+exit:
+    if (p)
+        pa_proplist_free(p);
+}
+
+static void handle_tone_stop(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+    struct userdata *u = (struct userdata *)userdata;
+    uint32_t stream_idx;
+    pa_sink_input *si;
+
+    pa_assert(conn);
+    pa_assert(msg);
+    pa_assert(userdata);
+
+    pa_assert_se(dbus_message_get_args(msg, NULL,
+                                       DBUS_TYPE_UINT32, &stream_idx,
+                                       DBUS_TYPE_INVALID));
+
+    pa_log_info("stop tone %u", stream_idx);
+
+    si = pa_idxset_get_by_index(u->module->core->sink_inputs, stream_idx);
+    if (!si) {
+        pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s",
+                            "org.tizen.multimedia.audio.InvalidState");
+        return;
+    }
+
+    pa_sink_input_kill(si);
+
+    pa_dbus_send_empty_reply(conn, msg);
+}
+
+#define TONE_PLAYER_INTROSPECT_XML                                      \
+    DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                           \
+    "<node>"                                                            \
+    " <interface name=\"TONE_PLAYER_INTERFACE\">"                       \
+    "  <method name=\"TONE_PLAYER_METHOD_NAME_TONE_PLAY\">"             \
+    "   <arg name=\"index\" direction=\"in\" type=\"u\"/>"               \
+    "   <arg name=\"duration\" direction=\"in\" type=\"i\"/>"           \
+    "   <arg name=\"client_pid\" direction=\"in\" type=\"i\"/>"         \
+    "   <arg name=\"role\" direction=\"in\" type=\"s\"/>"               \
+    "   <arg name=\"parent_id\" direction=\"in\" type=\"i\"/>"          \
+    "  </method>"                                                       \
+    "  <method name=\"TONE_PLAYER_METHOD_NAME_TONE_STOP\">"             \
+    "   <arg name=\"stream_idx\" direction=\"in\" type=\"i\"/>"         \
+    "  </method>"                                                       \
+    " </interface>"                                                     \
+    " <interface name=\"org.freedesktop.DBus.Introspectable\">"         \
+    "  <method name=\"Introspect\">"                                    \
+    "   <arg name=\"data\" type=\"s\" direction=\"out\"/>"              \
+    "  </method>"                                                       \
+    " </interface>"                                                     \
+    "</node>"
+
+static pa_dbus_arg_info tone_play_args[] = { { "index", "u", "in" },
+                                               { "duration", "i", "in" },
+                                               { "client_pid", "i", "in" },
+                                               { "role", "s", "in" },
+                                               { "parent_id", "i", "in" } };
+static pa_dbus_arg_info tone_stop_args[] = { { "stream_idx", "u", "in" } };
+static const char* signature_args_for_in[] = { "uiisi", "u" };
+
+static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
+    [METHOD_HANDLER_TONE_PLAY] = {
+        .method_name = TONE_PLAYER_METHOD_NAME_TONE_PLAY,
+        .arguments = tone_play_args,
+        .n_arguments = sizeof(tone_play_args) / sizeof(pa_dbus_arg_info),
+        .receive_cb = handle_tone_play },
+    [METHOD_HANDLER_TONE_STOP] = {
+        .method_name = TONE_PLAYER_METHOD_NAME_TONE_STOP,
+        .arguments = tone_stop_args,
+        .n_arguments = sizeof(tone_stop_args) / sizeof(pa_dbus_arg_info),
+        .receive_cb = handle_tone_stop }
+};
+
+static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+    const char *xml = TONE_PLAYER_INTROSPECT_XML;
+    DBusMessage *r = NULL;
+
+    pa_assert(conn);
+    pa_assert(msg);
+    pa_assert(userdata);
+
+    pa_assert_se(r = dbus_message_new_method_return(msg));
+    pa_assert_se(dbus_message_append_args(r, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID));
+
+    if (r) {
+        pa_assert_se(dbus_connection_send((conn), r, NULL));
+        dbus_message_unref(r);
+    }
+
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult handle_methods(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+    int idx = 0;
+
+    pa_assert(conn);
+    pa_assert(msg);
+    pa_assert(userdata);
+
+    for (idx = 0; idx < METHOD_HANDLER_MAX; idx++) {
+        if (dbus_message_is_method_call(msg, TONE_PLAYER_INTERFACE, method_handlers[idx].method_name)) {
+            if (pa_safe_streq(dbus_message_get_signature(msg), signature_args_for_in[idx])) {
+                method_handlers[idx].receive_cb(conn, msg, userdata);
+                return DBUS_HANDLER_RESULT_HANDLED;
+            } else {
+                pa_log_warn("Wrong Argument Signature");
+                pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_SIGNATURE,  "Wrong Signature, Expected %s", signature_args_for_in[idx]);
+                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+            }
+        }
+    }
+
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult method_handler_for_vt(DBusConnection *c, DBusMessage *m, void *userdata) {
+    struct userdata *u = userdata;
+    const char *path, *interface, *member;
+
+    pa_assert(c);
+    pa_assert(m);
+
+    path = dbus_message_get_path(m);
+    interface = dbus_message_get_interface(m);
+    member = dbus_message_get_member(m);
+
+    pa_log_debug("dbus: path=%s, interface=%s, member=%s", path, interface, member);
+
+    if (!pa_safe_streq(path, TONE_PLAYER_OBJECT_PATH))
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect"))
+        return handle_introspect(c, m, u);
+    else
+        return handle_methods(c, m, u);
+
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+int pa__init(pa_module *m) {
+    struct userdata *u;
+    DBusError err;
+
+    pa_dbus_connection *conn = NULL;
+    static const DBusObjectPathVTable vtable = {
+        .message_function = method_handler_for_vt,
+    };
+    pa_assert(m);
+
+    m->userdata = u = pa_xnew0(struct userdata, 1);
+    u->module = m;
+
+    if (!(conn = pa_dbus_bus_get(u->module->core, DBUS_BUS_SYSTEM, &err)) || dbus_error_is_set(&err)) {
+        if (conn)
+            pa_dbus_connection_unref(conn);
+
+        pa_log_error("Unable to contact D-Bus system bus: %s: %s", err.name, err.message);
+    } else
+        pa_log_debug("Got dbus connection");
+
+    u->dbus_conn = conn;
+    pa_assert_se(dbus_connection_register_object_path(pa_dbus_connection_get(conn),
+                 TONE_PLAYER_OBJECT_PATH, &vtable, u));
+
+    return 0;
+}
+
+void pa__done(pa_module *m) {
+    struct userdata *u;
+
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    if (u->dbus_conn)
+        pa_dbus_connection_unref(u->dbus_conn);
+
+    pa_xfree(u);
+}
+#endif
+
diff --git a/src/tones.h b/src/tones.h
new file mode 100644 (file)
index 0000000..9616d14
--- /dev/null
@@ -0,0 +1,649 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2020 Jaechul Lee <jcsing.lee@samsung.com>
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2.1 of the License,
+  or (at your option) any later version.
+
+  PulseAudio 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 Lesser General Public License
+  along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#ifndef footoneplayerfoo
+#define footoneplayerfoo
+#include <pulsecore/core.h>
+
+#define TONE_ELEMENTS_ROW                              14
+#define TONE_ELEMENTS_COLUMN                   6
+#define TONE_ELEMENTS                                  TONE_ELEMENTS_ROW * TONE_ELEMENTS_COLUMN
+
+/* need to improve: 18KiB approximately */
+static const uint16_t tones[][TONE_ELEMENTS] = {
+    {941, 1336, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // 0 key: 1336Hz, 941Hz
+
+    {697, 1209, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // 1 key: 1209Hz, 697Hz
+
+    {697, 1336, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // 2 key: 1336Hz, 697Hz
+
+    {697, 1477, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // 3 key: 1477Hz, 697Hz
+
+    {770, 1209, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // 4 key: 1209Hz, 770Hz
+
+    {770, 1336, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // 5 key: 1336Hz, 770Hz
+
+    {770, 1477, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // 6 key: 1477Hz, 770Hz
+
+    {852, 1209, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // 7 key: 1209Hz, 852Hz
+
+    {852, 1336, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // 8 key: 1336Hz, 852Hz
+
+    {852, 1477, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // 9 key: 1477Hz, 852Hz
+
+    // 10
+    {941, 1209, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // * key: 1209Hz, 941Hz
+
+    {941, 1477, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // # key: 1477Hz, 941Hz
+
+    {697, 1633, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // A key: 1633Hz, 697Hz
+
+    {770, 1633, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // B key: 1633Hz, 770Hz
+
+    {852, 1633, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // C key: 1633Hz, 852Hz
+
+    {941, 1633, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, // D key: 1633Hz, 941Hz
+
+    {425, 0, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Dial tone: CEPT: 425Hz, continuous
+
+    {350, 440, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Dial tone: ANSI (IS-95): 350Hz+440Hz, continuous
+
+    {400, 0, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Dial tone: JAPAN: 400Hz, continuous
+
+    {425, 0, 0, 500, 0, 0,
+    0, 0, 0, 500, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Busy: CEPT: 425Hz, 500ms ON, 500ms OFF...
+
+    // 20
+    {480, 620, 0, 500, 0, 0,
+    0, 0, 0, 500, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Busy: ANSI (IS-95): 480Hz+620Hz, 500ms ON, 500ms OFF...
+
+    {400, 0, 0, 500, 0, 0,
+    0, 0, 0, 500, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Busy: JAPAN: 400Hz, 500ms ON, 500ms OFF...
+
+    {425, 0, 0, 200, 0, 0,
+    0, 0, 0, 200, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //Call supervisory tone, Congestion: CEPT, JAPAN: 425Hz, 200ms ON, 200ms OFF
+
+    {480, 620, 0, 250, 0, 0,
+    0, 0, 0, 250, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Congestion: ANSI (IS-95): 480Hz+620Hz, 250ms ON, 250ms OFF...
+
+    {425, 0, 0, 200, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //Call supervisory tone, Radio path acknowledgment : CEPT, ANSI: 425Hz, 200ms ON
+
+    {400, 0, 0, 1000, 0, 0,
+    0, 0, 0, 2000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Radio path acknowledgment : JAPAN: 400Hz, 1s ON, 2s OFF...
+
+    {425, 0, 0, 200, 0, 0,
+    0, 0, 0, 200, 0, 0,
+    -1, -1, -1, -1, 3, 0}, //Call supervisory tone, Radio path not available: 425Hz, 200ms ON, 200 OFF 3 bursts
+
+    {950, 1400, 1800, 330, 0, 0,
+    0, 0, 0, 1000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Error/Special info: 950Hz+1400Hz+1800Hz, 330ms ON, 1s OFF...
+
+    {425, 0, 0, 200, 0, 0,
+    0, 0, 0, 600, 0, 0,
+    425, 0, 0, 200, 0, 0,
+    0, 0, 0, 3000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Call Waiting: CEPT, JAPAN: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF...
+
+    {440, 0, 0, 300, 0, 0,
+    0, 0, 0, 9700, 0, 0,
+    440, 0, 0, 100, 0, 0,
+    0, 0, 0, 100, 0, 0,
+    440, 0, 0, 100, 0, 0,
+    0, 0, 0, 9700, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Call Waiting: ANSI (IS-95): 440 Hz, 300 ms ON, 9.7 s OFF, (100 ms ON, 100 ms OFF, 100 ms ON, 9.7s OFF ...)
+
+    // 30
+    {425, 0, 0, 1000, 0, 0,
+    0, 0, 0, 4000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Ring Tone: CEPT, JAPAN: 425Hz, 1s ON, 4s OFF...
+
+    {440, 480, 0, 2000, 0, 0,
+    0, 0, 0, 4000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //Call supervisory tone, Ring Tone: ANSI (IS-95): 440Hz + 480Hz, 2s ON, 4s OFF...
+
+    {400, 1200, 0, 35, 0, 0,
+    -1, -1, -1, -1, 1, 0}, // General beep: 400Hz+1200Hz, 35ms ON
+
+    {1200, 0, 0, 100, 0, 0,
+    0, 0, 0, 100, 0, 0,
+    -1, -1, -1, -1, 2, 0}, //Proprietary tone, positive acknowlegement: 1200Hz, 100ms ON, 100ms OFF 2 bursts
+
+    {300, 400, 500, 400, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //Proprietary tone, negative acknowlegement: 300Hz+400Hz+500Hz, 400ms ON
+
+    {400, 1200, 0, 200, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //Proprietary tone, prompt tone: 400Hz+1200Hz, 200ms ON
+
+    {400, 1200, 0, 35, 0, 0,
+    0, 0, 0, 200, 0, 0,
+    400, 1200, 0, 35, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
+
+    {440, 0, 0, 250, 0, 0,
+    620, 0, 0, 250, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //Call supervisory tone (IS-95), intercept tone: alternating 440 Hz and 620 Hz tones, each on for 250 ms
+
+    {440, 0, 0, 250, 0, 0,
+    620, 0, 0, 250, 0, 0,
+    -1, -1, -1, -1, 8, 0}, //Call supervisory tone (IS-95), abbreviated intercept: intercept tone limited to 4 seconds
+
+    {480, 620, 0, 250, 0, 0,
+    0, 0, 0, 250, 0, 0,
+    -1, -1, -1, -1, 8, 0}, //Call supervisory tone (IS-95), abbreviated congestion: congestion tone limited to 4 seconds
+
+    // 40
+    {350, 440, 0, 100, 0, 0,
+    0, 0, 0, 100, 0, 0,
+    -1, -1, -1, -1, 3, 0}, //Call supervisory tone (IS-95), confirm tone: a 350 Hz tone added to a 440 Hz tone repeated 3 times in a 100 ms on, 100 ms off cycle
+
+    {480, 0, 0, 100, 0, 0,
+    0, 0, 0, 100, 0, 0,
+    -1, -1, -1, -1, 4, 0}, //Call supervisory tone (IS-95), pip tone: four bursts of 480 Hz tone (0.1 s on, 0.1 s off).
+
+    { 425, 0, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //425Hz continuous
+
+    {440, 480, 0, 2000, 0, 0,
+    0, 0, 0, 4000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA USA Ringback: 440Hz+480Hz 2s ON, 4000 OFF ...
+
+    {440, 0, 0, 250, 0, 0,
+    620, 0, 0, 250, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA Intercept tone: 440Hz 250ms ON, 620Hz 250ms ON ...
+
+    {440, 0, 0, 250, 0, 0,
+    620, 0, 0, 250, 0, 0,
+    -1, -1, -1, -1, 1, 0 }, //CDMA Abbr Intercept tone: 440Hz 250ms ON, 620Hz 250ms ON
+
+    {480, 620, 0, 250, 0, 0,
+    0, 0, 0, 250, 0, 0,
+    -1, -1, -1, -1, 0, 0 }, //CDMA Reorder tone: 480Hz+620Hz 250ms ON, 250ms OFF...
+
+    {480, 620, 0, 250, 0, 0,
+    0, 0, 0, 250, 0, 0,
+    -1, -1, -1, -1, 8, 0}, //CDMA Abbr Reorder tone: 480Hz+620Hz 250ms ON, 250ms OFF repeated for 8 times
+
+    {480, 620, 0, 500, 0, 0,
+    0, 0, 0, 500, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA Network Busy tone: 480Hz+620Hz 500ms ON, 500ms OFF continuous
+
+    {350, 440, 0, 100, 0, 0,
+    0, 0, 0, 100, 0, 0,
+    -1, -1, -1, -1, 3, 0}, //CDMA Confirm tone: 350Hz+440Hz 100ms ON, 100ms OFF repeated for 3 times
+
+    // 50
+    {660, 1000, 0, 500, 0, 0,
+    0, 0, 0, 100, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //CDMA answer tone: silent tone - definition Frequency 0, 0ms ON, 0ms OFF
+
+    {440, 0, 0, 300, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //CDMA Network Callwaiting tone: 440Hz 300ms ON
+
+    {480, 0, 0, 100, 0, 0,
+    0, 0, 0, 100, 0, 0,
+    -1, -1, -1, -1, 4, 0}, //CDMA PIP tone: 480Hz 100ms ON, 100ms OFF repeated for 4 times
+
+    {2090, 0, 0, 32, 0, 0,
+    2556, 0, 0, 64, 19, 0,
+    2090, 0, 0, 32, 0, 0,
+    2556, 0, 0, 48, 0, 0,
+    0, 0, 0, 4000, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //ISDN Call Signal Normal tone: {2091Hz 32ms ON, 2556 64ms ON} 20 times, 2091 32ms ON, 2556 48ms ON, 4s OFF
+
+    {2091, 0, 0, 32, 0, 0,
+    2556, 0, 0, 64, 7, 0,
+    2091, 0, 0, 32, 0, 0,
+    0, 0, 0, 400, 0, 0,
+    2091, 0, 0, 32, 0, 0,
+    2556, 0, 0, 64, 7, 4,
+    2091, 0, 0, 32, 0, 0,
+    0, 0, 0, 4000, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //ISDN Call Signal Intergroup tone: {2091Hz 32ms ON, 2556 64ms ON} 8 times, 2091Hz 32ms ON, 400ms OFF, {2091Hz 32ms ON, 2556Hz 64ms ON} 8times, 2091Hz 32ms ON, 4s OFF
+
+    {2091, 0, 0, 32, 0, 0,
+    2556, 0, 0, 64, 3, 0,
+    2091, 0, 0, 32, 0, 0,
+    0, 0, 0, 200, 0, 0,
+    2091, 0, 0, 32, 0, 0,
+    2556, 0, 0, 64, 3, 4,
+    2091, 0, 0, 32, 0, 0,
+    0, 0, 0, 200, 0, 0,
+    -1, -1, -1, -1, 1, 0},//ISDN Call Signal SP PRI tone:{2091Hz 32ms ON, 2556 64ms ON} 4 times 2091Hz 16ms ON, 200ms OFF, {2091Hz 32ms ON, 2556Hz 64ms ON} 4 times, 2091Hz 16ms ON, 200ms OFF
+
+    {0, 0, 0, -1, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //ISDN Call sign PAT3 tone: silent tone
+
+    {2091, 0, 0, 32, 0, 0,
+    2556, 0, 0, 64, 4, 0,
+    2091, 0, 0, 20, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //ISDN Ping Ring tone: {2091Hz 32ms ON, 2556Hz 64ms ON} 5 times 2091Hz 20ms ON
+
+    {0, 0, 0, -1, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //ISDN Pat5 tone: silent tone
+
+    {0, 0, 0, -1, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //ISDN Pat6 tone: silent tone
+
+    // 60
+    {0, 0, 0, -1, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //ISDN Pat7 tone: silent tone
+
+    {3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 39, 0,
+    0, 0, 0, 4000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //TONE_CDMA_HIGH_L tone: {3700Hz 25ms, 4000Hz 25ms} 40 times 4000ms OFF, Repeat ....
+
+    {2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 39, 0,
+    0, 0, 0, 4000, 0, 0,
+    -1, -1, -1, -1, 0, 0},//TONE_CDMA_MED_L tone: {2600Hz 25ms, 2900Hz 25ms} 40 times 4000ms OFF, Repeat ....
+
+    {1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 39, 0,
+    0, 0, 0, 4000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //TONE_CDMA_LOW_L tone: {1300Hz 25ms, 1450Hz 25ms} 40 times, 4000ms OFF, Repeat ....
+
+    {3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 15, 0,
+    0, 0, 0, 400, 0, 0,
+    -1, -1, -1, -1, 0, 0},//CDMA HIGH SS tone: {3700Hz 25ms, 4000Hz 25ms} repeat 16 times, 400ms OFF, repeat ....
+
+    {2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 15, 0,
+    0, 0, 0, 400, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA MED SS tone: {2600Hz 25ms, 2900Hz 25ms} repeat 16 times, 400ms OFF, repeat ....
+
+    {1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 15, 0,
+    0, 0, 0, 400, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA LOW SS tone: {1300z 25ms, 1450Hz 25ms} repeat 16 times, 400ms OFF, repeat ....
+
+    {3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 7, 0,
+    0, 0, 0, 200, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 7, 3,
+    0, 0, 0, 200, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 15, 6,
+    0, 0, 0, 4000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA HIGH SSL tone: {3700Hz 25ms, 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} repeat 8 times, 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} repeat 16 times, 4000ms OFF, repeat ...
+
+    {2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 7, 0,
+    0, 0, 0, 200, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 7, 3,
+    0, 0, 0, 200, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 15, 6,
+    0, 0, 0, 4000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA MED SSL tone: {2600Hz 25ms, 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} repeat 8 times, 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} repeat 16 times, 4000ms OFF, repeat ...
+
+    {1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 7, 0,
+    0, 0, 0, 200, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 7, 3,
+    0, 0, 0, 200, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 15, 6,
+    0, 0, 0, 4000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA LOW SSL tone: {1300Hz 25ms, 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} repeat 8 times, 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} repeat 16 times, 4000ms OFF, repeat ...
+
+    // 70
+    {3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 19, 0,
+    0, 0, 0, 1000, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 19, 3,
+    0, 0, 0, 3000, 0, 0,
+    -1, -1, -1, -1, 0, 0 },//CDMA HIGH SS2 tone: {3700Hz 25ms, 4000Hz 25ms} 20 times, 1000ms OFF, {3700Hz 25ms, 4000Hz 25ms} 20 times, 3000ms OFF, repeat ....
+
+    {2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 19, 0,
+    0, 0, 0, 1000, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 19, 3,
+    0, 0, 0, 3000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA MED SS2 tone: {2600Hz 25ms, 2900Hz 25ms} 20 times, 1000ms OFF, {2600Hz 25ms, 2900Hz 25ms} 20 times, 3000ms OFF, repeat ....
+
+    {1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 19, 0,
+    0, 0, 0, 1000, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 19, 3,
+    0, 0, 0, 3000, 0, 0,
+    -1, -1, -1, -1, 0, 0 }, //CDMA LOW SS2 tone: {1300Hz 25ms, 1450Hz 25ms} 20 times, 1000ms OFF, {1300Hz 25ms, 1450Hz 25ms} 20 times, 3000ms OFF, repeat ....
+
+    {3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 9, 0,
+    0, 0, 0, 500, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 19, 3,
+    0, 0, 0, 500, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 9, 6,
+    0, 0, 0, 3000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA HIGH SLS tone: {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 20 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 3000ms OFF, REPEAT....
+
+    {2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 9, 0,
+    0, 0, 0, 500, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 19, 3,
+    0, 0, 0, 500, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 9, 6,
+    0, 0, 0, 3000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA MED SLS tone: {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 20 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 3000ms OFF, REPEAT....
+
+    {1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 9, 0,
+    0, 0, 0, 500, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 19, 3,
+    0, 0, 0, 500, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 9, 6,
+    0, 0, 0, 3000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA LOW SLS tone: {1300Hz 25ms, 1450Hz 25ms} 10 times, 500ms OFF, {1300Hz 25ms, 1450Hz 25ms} 20 times, 500ms OFF, {1300Hz 25ms, 1450Hz 25ms} 10 times, 3000ms OFF, REPEAT....
+
+    {3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 9, 0,
+    0, 0, 0, 500, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 9, 3,
+    0, 0, 0, 500, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 9, 6,
+    0, 0, 0, 2500, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA HIGH S X4 tone: {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 2500ms OFF, REPEAT....
+
+    {2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 9, 0,
+    0, 0, 0, 500, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 9, 4,
+    0, 0, 0, 500, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 9, 6,
+    0, 0, 0, 2500, 0, 0,
+    -1, -1, -1, -1, 0, 0 }, //CDMA MED S X4 tone: {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 2500ms OFF, REPEAT....
+
+    {1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 9, 0,
+    0, 0, 0, 500, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 9, 3,
+    0, 0, 0, 500, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 9, 6,
+    0, 0, 0, 2500, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA LOW S X4 tone: {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 2500ms OFF, REPEAT....
+
+    {3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 19, 0,
+    0, 0, 0, 2000, 0, 0,
+    -1, -1, -1, -1, 0, 0 }, //CDMA HIGH PBX L: {3700Hz 25ms, 4000Hz 25ms}20 times, 2000ms OFF, REPEAT....
+
+    // 80
+    {2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 19, 0,
+    0, 0, 0, 2000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA MED PBX L: {2600Hz 25ms, 2900Hz 25ms}20 times, 2000ms OFF, REPEAT....
+
+    {1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 19, 0,
+    0, 0, 0, 2000, 0, 0,
+    -1, -1, -1, -1, 0, 0 }, //CDMA LOW PBX L: {1300Hz 25ms,1450Hz 25ms}20 times, 2000ms OFF, REPEAT....
+
+    {3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 7, 0,
+    0, 0, 0, 200, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 7, 3,
+    0, 0, 0, 2000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA HIGH PBX SS tone: {3700Hz 25ms, 4000Hz 25ms} 8 times 200 ms OFF, {3700Hz 25ms 4000Hz 25ms}8 times, 2000ms OFF, REPEAT....
+
+    {2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 7, 0,
+    0, 0, 0, 200, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 7, 3,
+    0, 0, 0, 2000, 0, 0,
+    -1, -1, -1, -1, 0, 0 }, //CDMA MED PBX SS tone: {2600Hz 25ms, 2900Hz 25ms} 8 times 200 ms OFF, {2600Hz 25ms 2900Hz 25ms}8 times, 2000ms OFF, REPEAT....
+
+    {1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 7, 0,
+    0, 0, 0, 200, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 7, 3,
+    0, 0, 0, 2000, 0, 0,
+    -1, -1, -1, -1, 0, 0 }, //CDMA LOW PBX SS tone: {1300Hz 25ms, 1450Hz 25ms} 8 times 200 ms OFF, {1300Hz 25ms 1450Hz 25ms}8 times, 2000ms OFF, REPEAT....
+
+    {3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 7, 0,
+    0, 0, 0, 200, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 7, 3,
+    0, 0, 0, 200, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 15, 6,
+    0, 0, 0, 1000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA HIGH PBX SSL tone:{3700Hz 25ms, 4000Hz 25ms} 8 times 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 16 times, 1000ms OFF, REPEAT....//
+
+    {2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 7, 0,
+    0, 0, 0, 200, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 7, 3,
+    0, 0, 0, 200, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 15, 6,
+    0, 0, 0, 1000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA MED PBX SSL tone:{2600Hz 25ms, 2900Hz 25ms} 8 times 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 16 times, 1000ms OFF, REPEAT....//
+
+    {1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 7, 0,
+    0, 0, 0, 200, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 7, 3,
+    0, 0, 0, 200, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 15, 6,
+    0, 0, 0, 1000, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA LOW PBX SSL tone:{1300Hz 25ms, 1450Hz 25ms} 8 times 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 16 times, 1000ms OFF, REPEAT....//
+
+    {3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 15, 0,
+    0, 0, 0, 200, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 7, 3,
+    0, 0, 0, 1000, 0, 0,
+    -1, -1, -1, -1, 0, 0 }, //CDMA HIGH PBX SLS tone:{3700Hz 25ms, 4000Hz 25ms} 8 times 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 16 times, 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 8 times, 1000ms OFF, REPEAT.... //
+
+    {2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 15, 0,
+    0, 0, 0, 200, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 7, 3,
+    0, 0, 0, 1000, 0, 0,
+    -1, -1, -1, -1, 0, 0 }, //CDMA HIGH PBX SLS tone:{2600Hz 25ms, 2900Hz 25ms} 8 times 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 16 times, 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 8 times, 1000ms OFF, REPEAT....//
+
+    // 90
+    {1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 15, 0,
+    0, 0, 0, 200, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 7, 3,
+    0, 0, 0, 1000, 0, 0,
+    -1, -1, -1, -1, 0, 0 }, //CDMA HIGH PBX SLS tone:{1300Hz 25ms, 1450Hz 25ms} 8 times 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 16 times, 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 8 times, 1000ms OFF, REPEAT....//
+
+    {3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 7, 0,
+    0, 0, 0, 200, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 7, 3,
+    0, 0, 0, 200, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 7, 6,
+    0, 0, 0, 200, 0, 0,
+    3700, 0, 0, 25, 0, 0,
+    4000, 0, 0, 25, 7, 9,
+    0, 0, 0, 800, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA HIGH PBX X S4 tone: {3700Hz 25ms 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms 4000Hz 25ms} 8 times, 800ms OFF, REPEAT...
+
+    {2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 7, 0,
+    0, 0, 0, 200, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 7, 3,
+    0, 0, 0, 200, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 7, 6,
+    0, 0, 0, 200, 0, 0,
+    2600, 0, 0, 25, 0, 0,
+    2900, 0, 0, 25, 7, 9,
+    0, 0, 0, 800, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA MED PBX X S4 tone: {2600Hz 25ms 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms 2900Hz 25ms} 8 times, 800ms OFF, REPEAT...
+
+    {1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 7, 0,
+    0, 0, 0, 200, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 7, 3,
+    0, 0, 0, 200, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 7, 6,
+    0, 0, 0, 200, 0, 0,
+    1300, 0, 0, 25, 0, 0,
+    1450, 0, 0, 25, 7, 9,
+    0, 0, 0, 800, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA LOW PBX X S4 tone: {1300Hz 25ms 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms 1450Hz 25ms} 8 times, 800ms OFF, REPEAT...
+
+    {1109, 0, 0, 62, 0, 0,
+    784, 0, 0, 62, 0, 0,
+    740, 0, 0, 62, 0, 0,
+    622, 0, 0, 62, 0, 0,
+    1109, 0, 0, 62, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //CDMA Alert Network Lite tone: 1109Hz 62ms ON, 784Hz 62ms ON, 740Hz 62ms ON 622Hz 62ms ON, 1109Hz 62ms ON
+
+    {1245, 0, 0, 62, 0, 0,
+    659, 0, 0, 62, 0, 0,
+    1245, 0, 0, 62, 0, 0,
+    659, 0, 0, 62, 0, 0,
+    1245, 0, 0, 62, 0, 0,
+    659, 0, 0, 62, 0, 0,
+    1245, 0, 0, 62, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //CDMA Alert Auto Redial tone: {1245Hz 62ms ON, 659Hz 62ms ON} 3 times, 1245 62ms ON//
+
+    {1150, 770, 0, 400, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //CDMA One Min Beep tone: 1150Hz+770Hz 400ms ON//
+
+    {941, 1477, 0, 120, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //CDMA KEYPAD Volume key lite tone: 941Hz+1477Hz 120ms ON
+
+    {587, 0, 0, 375, 0, 0,
+    1175, 0, 0, 125, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //CDMA PRESSHOLDKEY LITE tone: 587Hz 375ms ON, 1175Hz 125ms ON
+
+    {587, 0, 0, 62, 0, 0,
+    784, 0, 0, 62, 0, 0,
+    831, 0, 0, 62, 0, 0,
+    784, 0, 0, 62, 0, 0,
+    1109, 0, 0, 62, 0, 0,
+    784, 0, 0, 62, 0, 0,
+    831, 0, 0, 62, 0, 0,
+    784, 0, 0, 62, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //CDMA ALERT INCALL LITE tone: 587Hz 62ms, 784 62ms, 831Hz 62ms, 784Hz 62ms, 1109 62ms, 784Hz 62ms, 831Hz 62ms, 784Hz 62ms
+
+    // 100
+    {941, 0, 0, 125, 0, 0,
+    0, 0, 0, 10, 0, 0,
+    941, 0, 0, 125, 0, 0,
+    0, 0, 0, 10, 0, 0,
+    1245, 0, 0, 62, 0, 0,
+    0, 0, 0, 10, 0, 0,
+    0, 0, 0, 4990, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //CDMA EMERGENCY RINGBACK tone: {941Hz 125ms ON, 10ms OFF} 3times 4990ms OFF, REPEAT...
+
+    {1319, 0, 0, 125, 0, 0,
+    0, 0, 0, 125, 0, 0,
+    -1, -1, -1, -1, 3, 0 }, //CDMA ALERT CALL GUARD tone: {1319Hz 125ms ON, 125ms OFF} 3 times
+
+    {1047, 0, 0, 125, 0, 0,
+    370, 0, 0, 125, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //CDMA SOFT ERROR LITE tone: 1047Hz 125ms ON, 370Hz 125ms
+
+    {1480, 0, 0, 125, 0, 0,
+    1397, 0, 0, 125, 0, 0,
+    784, 0, 0, 125, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //CDMA CALLDROP LITE tone: 1480Hz 125ms, 1397Hz 125ms, 784Hz 125ms//
+
+    {425, 0, 0, 125, 0, 0,
+    0, 0, 0, 125, 0, 0,
+    -1, -1, -1, -1, 1, 0},//CDMA_NETWORK_BUSY_ONE_SHOT tone: 425Hz 500ms ON, 500ms OFF
+
+    {1150, 770, 0, 400, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //CDMA_ABBR_ALERT tone: 1150Hz+770Hz 400ms ON
+
+    {0, 0, 0, -1, 0, 0,
+    -1, -1, -1, -1, 1, 0}, //CDMA_SIGNAL_OFF - silent tone
+
+    {100, 0, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //100Hz continuous
+
+    {200, 0, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //200Hz continuous
+
+    {300, 0, 0, -1, 0, 0,
+    -1, -1, -1, -1, 0, 0}, //300Hz continuous
+};
+#endif
+