/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 2 -*-
 *
 * Copyright (C) 2009 Canonical Ltd.
 * Authors:
 *  Gustavo Sverzut Barbieri <gustavo.barbieri@canonical.com>
 *
 * This file is part of Netbook Launcher EFL.
 *
 * Netbook Launcher EFL 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.
 *
 * Netbook Launcher EFL 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 Netbook Launcher EFL.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "netbook-launcher.h"
#include <Ecore_Evas.h>
#include <Ecore_X.h>
#include <canberra.h>

static unsigned int _init_count = 0;
static Eina_Bool _sound_disabled = 1;
static ca_context *_sound_context = NULL;

Eina_Bool
sound_play(Evas_Object *obj, const char *sound_id)
{
  Evas *e;
  Ecore_Evas *ee;
  const char *win_name, *win_class, *win_cname;
  char win_id[128], win_xid[32], ev_x[32], ev_y[32], ev_button[32], *win_icon;
  Ecore_X_Window xid;
  int err, x, y, wx, wy, i, bmask;

  if (!sound_id)
  {
    ERR("sound_id == NULL\n");
    return 0;
  }

  if (!_sound_context)
  {
    DBG("no sound context to play '%s' for object %p\n", sound_id, obj);
    return 0;
  }

  if (_sound_disabled)
  {
    DBG("sound disabled, not playing '%s' for object %p\n", sound_id, obj);
    return 0;
  }

  e = evas_object_evas_get(obj);
  if (!e)
  {
    ERR("could not get evas of object %p\n", obj);
    return 0;
  }
  ee = ecore_evas_ecore_evas_get(e);
  if (!ee)
  {
    ERR("no ecore evas for evas %p\n", e);
    return 0;
  }

  xid = ecore_evas_window_get(ee);
  win_name = ecore_evas_title_get(ee);
  ecore_evas_name_class_get(ee, &win_cname, &win_class);
  win_icon = ecore_x_icccm_icon_name_get(xid);

  snprintf(win_id, sizeof(win_id), "%s#%s",
           win_cname ? win_cname : "", win_class ? win_class : "");
  snprintf(win_xid, sizeof(win_xid), "%lu", (long unsigned)xid);

  evas_pointer_output_xy_get(e, &x, &y);
  ecore_evas_geometry_get(ee, &wx, &wy, NULL, NULL);
  x += wx;
  y += wy;
  snprintf(ev_x, sizeof(ev_x), "%d", x);
  snprintf(ev_y, sizeof(ev_y), "%d", y);
  bmask = evas_pointer_button_down_mask_get(e);

  ev_button[0] = '\0';
  for (i = 0; i < 3; i++)
    if (bmask & (1 << i))
    {
      snprintf(ev_button, sizeof(ev_button), "%d", i + 1);
      break;
    }

  err = ca_context_play
    (_sound_context, 0,
     CA_PROP_EVENT_ID, sound_id,
     CA_PROP_CANBERRA_CACHE_CONTROL, "volatile",
     CA_PROP_WINDOW_NAME, win_name ? win_name : "",
     CA_PROP_WINDOW_ICON, win_icon ? win_icon : "",
     CA_PROP_WINDOW_ID, win_id,
     CA_PROP_WINDOW_X11_XID, win_xid,
     CA_PROP_EVENT_MOUSE_X, ev_x,
     CA_PROP_EVENT_MOUSE_Y, ev_y,
     CA_PROP_EVENT_MOUSE_BUTTON, ev_button,
     NULL);

  free(win_icon);

  if (err != CA_SUCCESS)
  {
    INF("could not play sound '%s' for object %p at (%d,%d): %s\n",
        sound_id, obj, x, y, ca_strerror(err));
    return 0;
  }

  return 1;
}

unsigned int
sound_init(void)
{
  int err, argc;
  char **argv = NULL;

  _init_count++;
  if (_init_count > 1) return _init_count;

  err = ca_context_create(&_sound_context);
  if (err != CA_SUCCESS)
  {
    ERR("could not init libcanberra: %s\n", ca_strerror(err));
    _init_count = 0;
    return 0;
  }

  ecore_app_args_get(&argc, &argv);

  err = ca_context_change_props
    (_sound_context,
     CA_PROP_APPLICATION_NAME, argv ? argv[0] : PACKAGE,
     CA_PROP_APPLICATION_VERSION, PACKAGE_VERSION,
     NULL);
  if (err != CA_SUCCESS)
    WRN("could not set basic sound properties: %s\n", ca_strerror(err));

  return _init_count;
}

unsigned int
sound_shutdown(void)
{
  int err;

  if (_init_count == 0) return 0;
  _init_count--;
  if (_init_count > 0) return _init_count;
  if (!_sound_context)
  {
    WRN("no sound context.\n");
    return 0;
  }

  err = ca_context_destroy(_sound_context);
  if (err != CA_SUCCESS)
  {
    ERR("could not destroy sound context: %s\n", ca_strerror(err));
    return 0;
  }
  _sound_context = NULL;

  return 0;
}

Eina_Bool
sound_theme_set(const char *xdg_theme)
{
  int err;

  if (!_sound_context)
  {
    ERR("no sound context.\n");
    return 0;
  }

  err = ca_context_change_props
    (_sound_context, CA_PROP_CANBERRA_XDG_THEME_NAME, xdg_theme, NULL);
  if (err != CA_SUCCESS)
  {
    ERR("could set sound theme '%s': %s\n", xdg_theme, ca_strerror(err));
    return 0;
  }

  return 1;
}

Eina_Bool
sound_enable_set(Eina_Bool enabled)
{
  int err;

  if (!_sound_context)
  {
    ERR("no sound context.\n");
    return 0;
  }

  _sound_disabled = !enabled;
  err = ca_context_change_props
    (_sound_context, CA_PROP_CANBERRA_ENABLE, enabled ? "1" : "0", NULL);
  if (err != CA_SUCCESS)
  {
    ERR("could %s sound: %s\n", enabled ? "enable" : "disable",
        ca_strerror(err));
    return 0;
  }

  return 1;
}
