Skip to content
Permalink
Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
400 lines (355 sloc) 11.6 KB
/* Audacious LIRC plugin - lirc.c
Copyright (C) 2012 Joonas Harjumäki (jharjuma@gmail.com)
Copyright (C) 2005 Audacious development team
Copyright (c) 1998-1999 Carl van Schaik (carl@leg.uct.ac.za)
Copyright (C) 2000 Christoph Bartelmus (xmms@bartelmus.de)
some code was stolen from:
IRman plugin for xmms by Charles Sielski (stray@teklabs.net)
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; either version 2 of the License, or
(at your option) any later version.
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <glib.h>
#include <lirc/lirc_client.h>
#include <libaudcore/drct.h>
#include <libaudcore/i18n.h>
#include <libaudcore/runtime.h>
#include <libaudcore/playlist.h>
#include <libaudcore/plugin.h>
#include <libaudcore/preferences.h>
#include <libaudcore/hook.h>
class LIRCPlugin : public GeneralPlugin
{
public:
static const char about[];
static const char * const defaults[];
static const PreferencesWidget widgets[];
static const PluginPreferences prefs;
static constexpr PluginInfo info = {
N_("LIRC Plugin"),
PACKAGE,
about,
& prefs
};
constexpr LIRCPlugin () : GeneralPlugin (info, false) {}
bool init ();
void cleanup ();
};
EXPORT LIRCPlugin aud_plugin_instance;
static gboolean lirc_input_callback (GIOChannel * source, GIOCondition condition, void * data);
const char * const LIRCPlugin::defaults[] = {
"enable_reconnect", "TRUE",
"reconnect_timeout", "5",
nullptr};
int lirc_fd = -1;
struct lirc_config *config = nullptr;
int tracknr = 0;
int mute = 0; /* mute flag */
int mute_vol = 0; /* holds volume before mute */
unsigned input_tag;
char track_no[64];
int track_no_pos;
int tid;
void init_lirc ()
{
int flags;
if ((lirc_fd = lirc_init ((char *) "audacious", 1)) == -1)
{
AUDERR ("could not init LIRC support\n");
return;
}
if (lirc_readconfig (nullptr, &config, nullptr) == -1)
{
lirc_deinit ();
AUDERR ("could not read LIRC config file\n");
return;
}
input_tag =
g_io_add_watch (g_io_channel_unix_new (lirc_fd), G_IO_IN,
lirc_input_callback, nullptr);
fcntl (lirc_fd, F_SETOWN, getpid ());
flags = fcntl (lirc_fd, F_GETFL, 0);
if (flags != -1)
{
fcntl (lirc_fd, F_SETFL, flags | O_NONBLOCK);
}
}
bool LIRCPlugin::init ()
{
aud_config_set_defaults ("lirc", defaults);
init_lirc ();
track_no_pos = 0;
tid = 0;
return true;
}
gboolean reconnect_lirc (void * data)
{
AUDERR ("trying to reconnect...\n");
aud_plugin_instance.init ();
return (lirc_fd == -1);
}
void LIRCPlugin::cleanup ()
{
if (config)
{
if (input_tag)
g_source_remove (input_tag);
config = nullptr;
}
if (lirc_fd != -1)
{
lirc_deinit ();
lirc_fd = -1;
}
}
gboolean jump_to (void * data)
{
auto playlist = Playlist::active_playlist ();
playlist.set_position (atoi (track_no) - 1);
track_no_pos = 0;
tid = 0;
return false;
}
static gboolean lirc_input_callback (GIOChannel * source, GIOCondition condition, void * data)
{
char *code;
char *c;
int output_time, v;
int ret;
char *ptr;
int balance;
#if 0
gboolean show_pl;
#endif
int n;
char *utf8_title_markup;
while ((ret = lirc_nextcode (&code)) == 0 && code != nullptr)
{
while ((ret = lirc_code2char (config, code, &c)) == 0 && c != nullptr)
{
if (g_ascii_strcasecmp ("PLAY", c) == 0)
aud_drct_play ();
else if (g_ascii_strcasecmp ("STOP", c) == 0)
aud_drct_stop ();
else if (g_ascii_strcasecmp ("PAUSE", c) == 0)
aud_drct_pause ();
else if (g_ascii_strcasecmp ("PLAYPAUSE", c) == 0)
aud_drct_play_pause ();
else if (g_ascii_strncasecmp ("NEXT", c, 4) == 0)
{
ptr = c + 4;
while (g_ascii_isspace (*ptr))
ptr++;
n = atoi (ptr);
if (n <= 0)
n = 1;
for (; n > 0; n--)
{
aud_drct_pl_next ();
}
}
else if (g_ascii_strncasecmp ("PREV", c, 4) == 0)
{
ptr = c + 4;
while (g_ascii_isspace (*ptr))
ptr++;
n = atoi (ptr);
if (n <= 0)
n = 1;
for (; n > 0; n--)
{
aud_drct_pl_prev ();
}
}
else if (g_ascii_strcasecmp ("SHUFFLE", c) == 0)
aud_toggle_bool ("shuffle");
else if (g_ascii_strcasecmp ("REPEAT", c) == 0)
aud_toggle_bool ("repeat");
else if (g_ascii_strncasecmp ("FWD", c, 3) == 0)
{
ptr = c + 3;
while (g_ascii_isspace (*ptr))
ptr++;
n = atoi (ptr) * 1000;
if (n <= 0)
n = 5000;
output_time = aud_drct_get_time ();
aud_drct_seek (output_time + n);
}
else if (g_ascii_strncasecmp ("BWD", c, 3) == 0)
{
ptr = c + 3;
while (g_ascii_isspace (*ptr))
ptr++;
n = atoi (ptr) * 1000;
if (n <= 0)
n = 5000;
output_time = aud_drct_get_time ();
aud_drct_seek (output_time - n);
}
else if (g_ascii_strncasecmp ("VOL_UP", c, 6) == 0)
{
ptr = c + 6;
while (g_ascii_isspace (*ptr))
ptr++;
n = atoi (ptr);
if (n <= 0)
n = 5;
v = aud_drct_get_volume_main ();
if (v > (100 - n))
v = 100 - n;
aud_drct_set_volume_main (v + n);
}
else if (g_ascii_strncasecmp ("VOL_DOWN", c, 8) == 0)
{
ptr = c + 8;
while (g_ascii_isspace (*ptr))
ptr++;
n = atoi (ptr);
if (n <= 0)
n = 5;
v = aud_drct_get_volume_main ();
if (v < n)
v = n;
aud_drct_set_volume_main (v - n);
}
else if (g_ascii_strcasecmp ("QUIT", c) == 0)
{
aud_quit ();
}
else if (g_ascii_strcasecmp ("MUTE", c) == 0)
{
if (mute == 0)
{
mute = 1;
/* store the master volume so
we can restore it on unmute. */
mute_vol = aud_drct_get_volume_main ();
aud_drct_set_volume_main (0);
}
else
{
mute = 0;
aud_drct_set_volume_main (mute_vol);
}
}
else if (g_ascii_strncasecmp ("BAL_LEFT", c, 8) == 0)
{
ptr = c + 8;
while (g_ascii_isspace (*ptr))
ptr++;
n = atoi (ptr);
if (n <= 0)
n = 5;
balance = aud_drct_get_volume_balance ();
balance -= n;
if (balance < -100)
balance = -100;
aud_drct_set_volume_balance (balance);
}
else if (g_ascii_strncasecmp ("BAL_RIGHT", c, 9) == 0)
{
ptr = c + 9;
while (g_ascii_isspace (*ptr))
ptr++;
n = atoi (ptr);
if (n <= 0)
n = 5;
balance = aud_drct_get_volume_balance ();
balance += n;
if (balance > 100)
balance = 100;
aud_drct_set_volume_balance (balance);
}
else if (g_ascii_strcasecmp ("BAL_CENTER", c) == 0)
{
balance = 0;
aud_drct_set_volume_balance (balance);
}
else if (g_ascii_strcasecmp ("LIST", c) == 0)
{
#if 0
show_pl = aud_drct_pl_win_is_visible ();
show_pl = (show_pl) ? 0 : 1;
aud_drct_pl_win_toggle (show_pl);
#endif
}
else if (g_ascii_strcasecmp ("PLAYLIST_CLEAR", c) == 0)
{
aud_drct_stop ();
Playlist::active_playlist ().remove_all_entries ();
}
else if (g_ascii_strncasecmp ("PLAYLIST_ADD ", c, 13) == 0)
{
aud_drct_pl_add (c + 13, -1);
}
else if ((strlen (c) == 1) && ((*c >= '0') || (*c <= '9')))
{
if (track_no_pos < 63)
{
if (tid)
g_source_remove (tid);
track_no[track_no_pos++] = *c;
track_no[track_no_pos] = 0;
tid = g_timeout_add (1500, jump_to, nullptr);
utf8_title_markup = g_markup_printf_escaped ("%s", track_no);
hook_call ("aosd toggle", utf8_title_markup);
g_free (utf8_title_markup);
}
}
else
{
AUDERR ("unknown command \"%s\"\n", c);
}
}
g_free (code);
if (ret == -1)
break;
}
if (ret == -1)
{
/* something went badly wrong */
AUDERR ("disconnected from LIRC\n");
aud_plugin_instance.cleanup ();
if (aud_get_bool ("lirc", "enable_reconnect"))
{
int reconnect_timeout = aud_get_int ("lirc", "reconnect_timeout");
AUDERR ("will try reconnect every %d seconds...\n", reconnect_timeout);
g_timeout_add (1000 * reconnect_timeout, reconnect_lirc, nullptr);
}
}
return true;
}
const char LIRCPlugin::about[] =
N_("A simple plugin to control Audacious using the LIRC remote control daemon\n\n"
"Adapted for Audacious by:\n"
"Tony Vroon <chainsaw@gentoo.org>\n"
"Joonas Harjumäki <jharjuma@gmail.com>\n\n"
"Based on the XMMS LIRC plugin by:\n"
"Carl van Schaik <carl@leg.uct.ac.za>\n"
"Christoph Bartelmus <xmms@bartelmus.de>\n"
"Andrew O. Shadoura <bugzilla@tut.by>\n\n"
"For more information about LIRC, see http://lirc.org.");
const PreferencesWidget LIRCPlugin::widgets[] = {
WidgetLabel (N_("<b>Connection</b>")),
WidgetCheck (N_("Reconnect to LIRC server"),
WidgetBool ("lirc", "enable_reconnect")),
WidgetSpin (N_("Wait before reconnecting:"),
WidgetInt ("lirc", "reconnect_timeout"),
{1, 120, 1, N_("seconds")},
WIDGET_CHILD)
};
const PluginPreferences LIRCPlugin::prefs = {{widgets}};
You can’t perform that action at this time.