mangler-1.2.5/ 0000755 0000765 0000062 00000000000 12075675561 011126 5 ustar staff mangler-1.2.5/src/ 0000755 0000765 0000062 00000000000 12075675561 011715 5 ustar staff mangler-1.2.5/src/._manglerui.h 0000644 0000765 0000062 00000000336 12075416741 014261 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglersettings.h 0000644 0000765 0000062 00000016212 11602153752 015262 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglersettings.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLERSETTINGS_H
#define _MANGLERSETTINGS_H
#include "manglerconfig.h"
#include
class ManglerSettings
{
public:
ManglerSettings(Glib::RefPtr builder);
Glib::RefPtr builder;
Gtk::Window *settingsWindow;
Gtk::Button *button;
Gtk::Label *label;
Gtk::ComboBox *combobox;
Gtk::Window *window;
Gtk::CheckButton *checkbutton;
Gtk::VBox *vbox;
Gtk::Table *table;
Gtk::SpinButton *spinbutton;
Gtk::HScale *volumehscale;
Gtk::Adjustment *volumeAdjustment;
Gtk::Adjustment *gainAdjustment;
Gtk::HScale *gainhscale;
sigc::connection volumeAdjustSignalConnection;
bool isDetectingKey;
bool isDetectingMouse;
std::map mouseInputDevices;
ManglerConfig config;
// Audio Player List Combo Box Setup
Gtk::ComboBox *audioPlayerComboBox;
class audioPlayerModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
audioPlayerModelColumns() { add(id); add(name); }
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn name;
};
audioPlayerModelColumns audioPlayerColumns;
Glib::RefPtr audioPlayerTreeModel;
Gtk::ComboBox *audioSubsystemComboBox;
class audioSubsystemModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
audioSubsystemModelColumns() { add(id); add(name); }
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn name;
};
audioSubsystemModelColumns audioSubsystemColumns;
Glib::RefPtr audioSubsystemTreeModel;
// Input Device Combo Box Setup
Gtk::ComboBox *inputDeviceComboBox;
class inputDeviceModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
inputDeviceModelColumns() { add(id); add(name); add(description); }
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn name;
Gtk::TreeModelColumn description;
};
inputDeviceModelColumns inputColumns;
Glib::RefPtr inputDeviceTreeModel;
Gtk::Entry *inputDeviceCustomName;
// Output Device Combo Box Setup
Gtk::ComboBox *outputDeviceComboBox;
class outputDeviceModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
outputDeviceModelColumns() { add(id); add(name); add(description); }
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn name;
Gtk::TreeModelColumn description;
};
outputDeviceModelColumns outputColumns;
Glib::RefPtr outputDeviceTreeModel;
Gtk::Entry *outputDeviceCustomName;
// Notification Device Combo Box Setup
Gtk::ComboBox *notificationDeviceComboBox;
class notificationDeviceModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
notificationDeviceModelColumns() { add(id); add(name); add(description); }
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn name;
Gtk::TreeModelColumn description;
};
notificationDeviceModelColumns notificationColumns;
Glib::RefPtr notificationDeviceTreeModel;
Gtk::Entry *notificationDeviceCustomName;
// Mouse Input Device Combo Box Setup
Gtk::ComboBox *mouseDeviceComboBox;
class mouseDeviceModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
mouseDeviceModelColumns() { add(id); add(name); }
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn name;
};
mouseDeviceModelColumns mouseColumns;
Glib::RefPtr mouseDeviceTreeModel;
// on screen display position/alignment
class osdColumns : public Gtk::TreeModel::ColumnRecord
{
public:
osdColumns() { add(id); add(name); }
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn name;
};
osdColumns osdPositionColumns, osdAlignmentColumns;
Glib::RefPtr osdPositionModel, osdAlignmentModel;
Gtk::ComboBox *osdPosition, *osdAlignment;
Gtk::SpinButton *osdFontSize;
Gtk::ColorButton *osdColor;
// members functions
void showSettingsWindow(void);
bool settingsPTTKeyDetect(void);
bool settingsPTTMouseDetect(void);
void applySettings(void);
void initSettings(void);
std::map getInputDeviceList(void);
// callbacks
void settingsWindow_show_cb(void);
void settingsWindow_hide_cb(void);
void settingsCancelButton_clicked_cb(void);
void settingsApplyButton_clicked_cb(void);
void settingsOkButton_clicked_cb(void);
void settingsEnablePTTKeyCheckButton_toggled_cb(void);
void settingsPTTKeyButton_clicked_cb(void);
void settingsEnablePTTMouseCheckButton_toggled_cb(void);
void settingsPTTMouseButton_clicked_cb(void);
void settingsEnableAudioIntegrationCheckButton_toggled_cb(void);
void settingsEnableVoiceActivationCheckButton_toggled_cb(void);
void settingsEnableOnScreenDisplayCheckButton_toggled_cb(void);
void audioSubsystemComboBox_changed_cb(void);
void updateDeviceComboBoxes(void);
void inputDeviceComboBox_changed_cb(void);
void outputDeviceComboBox_changed_cb(void);
void notificationDeviceComboBox_changed_cb(void);
};
#endif
mangler-1.2.5/src/._manglersettings.h 0000644 0000765 0000062 00000000336 11602153752 015477 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglersettings.cpp 0000644 0000765 0000062 00000130121 11757473570 015627 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2012-05-24 20:01:28 +0200 (Thu, 24 May 2012) $
* $Revision: 1160 $
* $LastChangedBy: Haxar $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglersettings.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "config.h"
#include "mangler.h"
#include "manglersettings.h"
#include
#include "manglerintegration.h"
#include "mangleraudio.h"
#ifdef HAVE_XOSD
# include "manglerosd.h"
#endif
#define PTT_KEY_GET "<press the set button to define a hotkey>"
#define PTT_KEY_SET "<Hold a key combination and click done...>"
#define PTT_MOUSE_GET "<press the set button to define a button>"
#define PTT_MOUSE_SET "<Click a mouse button you wish to use...>"
ManglerSettings::ManglerSettings(Glib::RefPtr builder) {/*{{{*/
this->builder = builder;
// Connect our signals for this window
builder->get_widget("settingsWindow", settingsWindow);
/*
* Set window properties that are not settable in builder
*/
settingsWindow->set_keep_above(true);
settingsWindow->signal_show().connect(sigc::mem_fun(this, &ManglerSettings::settingsWindow_show_cb));
settingsWindow->signal_hide().connect(sigc::mem_fun(this, &ManglerSettings::settingsWindow_hide_cb));
builder->get_widget("settingsCancelButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerSettings::settingsCancelButton_clicked_cb));
builder->get_widget("settingsApplyButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerSettings::settingsApplyButton_clicked_cb));
builder->get_widget("settingsOkButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerSettings::settingsOkButton_clicked_cb));
builder->get_widget("settingsEnablePTTKeyCheckButton", checkbutton);
checkbutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerSettings::settingsEnablePTTKeyCheckButton_toggled_cb));
builder->get_widget("settingsPTTKeyButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerSettings::settingsPTTKeyButton_clicked_cb));
builder->get_widget("settingsEnablePTTMouseCheckButton", checkbutton);
checkbutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerSettings::settingsEnablePTTMouseCheckButton_toggled_cb));
builder->get_widget("settingsPTTMouseButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerSettings::settingsPTTMouseButton_clicked_cb));
builder->get_widget("settingsEnableAudioIntegrationCheckButton", checkbutton);
checkbutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerSettings::settingsEnableAudioIntegrationCheckButton_toggled_cb));
builder->get_widget("settingsAudioIntegrationComboBox", audioPlayerComboBox);
audioPlayerTreeModel = Gtk::ListStore::create(audioPlayerColumns);
audioPlayerComboBox->set_model(audioPlayerTreeModel);
// create a "none" row
Gtk::TreeModel::Row audioPlayerNoneRow = *(audioPlayerTreeModel->append());
audioPlayerNoneRow[audioPlayerColumns.id] = MusicClient_None;
audioPlayerNoneRow[audioPlayerColumns.name] = "None";
#ifdef HAVE_LIBMPDCLIENT
// add MPD row
Gtk::TreeModel::Row audioPlayerMPDRow = *(audioPlayerTreeModel->append());
audioPlayerMPDRow[audioPlayerColumns.id] = MusicClient_MPD;
audioPlayerMPDRow[audioPlayerColumns.name] = "MPD";
#endif
#ifdef HAVE_DBUS
// add DBUS client rows
// rhythmbox
Gtk::TreeModel::Row audioPlayerRBRow = *(audioPlayerTreeModel->append());
audioPlayerRBRow[audioPlayerColumns.id] = MusicClient_Rhythmbox;
audioPlayerRBRow[audioPlayerColumns.name] = "Rhythmbox";
// amarok
Gtk::TreeModel::Row audioPlayerAmarokRow = *(audioPlayerTreeModel->append());
audioPlayerAmarokRow[audioPlayerColumns.id] = MusicClient_Amarok;
audioPlayerAmarokRow[audioPlayerColumns.name] = "Amarok";
#endif
audioPlayerComboBox->pack_start(audioPlayerColumns.name);
audioPlayerComboBox->set_active(audioPlayerNoneRow);
builder->get_widget("settingsEnableVoiceActivationCheckButton", checkbutton);
checkbutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerSettings::settingsEnableVoiceActivationCheckButton_toggled_cb));
#ifdef HAVE_XOSD
builder->get_widget("settingsOSD", vbox);
vbox->set_sensitive(true);
builder->get_widget("settingsEnableOnScreenDisplayCheckButton", checkbutton);
checkbutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerSettings::settingsEnableOnScreenDisplayCheckButton_toggled_cb));
builder->get_widget("settingsOSDverticalPos", osdPosition);
osdPositionModel = Gtk::ListStore::create(osdPositionColumns);
osdPosition->set_model(osdPositionModel);
osdPosition->pack_start(osdPositionColumns.name);
Gtk::TreeModel::Row posrow;
posrow = *osdPositionModel->append();
posrow[osdPositionColumns.id] = XOSD_top; posrow[osdPositionColumns.name] = "Top";
posrow = *osdPositionModel->append();
posrow[osdPositionColumns.id] = XOSD_middle; posrow[osdPositionColumns.name] = "Middle";
posrow = *osdPositionModel->append();
posrow[osdPositionColumns.id] = XOSD_bottom; posrow[osdPositionColumns.name] = "Bottom";
builder->get_widget("settingsOSDhorizontalPos", osdAlignment);
osdAlignmentModel = Gtk::ListStore::create(osdAlignmentColumns);
osdAlignment->set_model(osdAlignmentModel);
osdAlignment->pack_start(osdAlignmentColumns.name);
Gtk::TreeModel::Row alnrow;
alnrow = *osdAlignmentModel->append();
alnrow[osdAlignmentColumns.id] = XOSD_center; alnrow[osdAlignmentColumns.name] = "Center";
alnrow = *osdAlignmentModel->append();
alnrow[osdAlignmentColumns.id] = XOSD_left; alnrow[osdAlignmentColumns.name] = "Left";
alnrow = *osdAlignmentModel->append();
alnrow[osdAlignmentColumns.id] = XOSD_right; alnrow[osdAlignmentColumns.name] = "Right";
builder->get_widget("settingsOSDfontsize", osdFontSize);
builder->get_widget("settingsOSDcolor", osdColor);
#endif
builder->get_widget("audioSubsystemComboBox", audioSubsystemComboBox);
audioSubsystemTreeModel = Gtk::ListStore::create(audioSubsystemColumns);
audioSubsystemComboBox->set_model(audioSubsystemTreeModel);
audioSubsystemComboBox->pack_start(audioSubsystemColumns.name);
audioSubsystemComboBox->signal_changed().connect(sigc::mem_fun(this, &ManglerSettings::audioSubsystemComboBox_changed_cb));
builder->get_widget("inputDeviceComboBox", inputDeviceComboBox);
inputDeviceTreeModel = Gtk::ListStore::create(inputColumns);
inputDeviceComboBox->set_model(inputDeviceTreeModel);
inputDeviceComboBox->pack_start(inputColumns.description);
inputDeviceComboBox->signal_changed().connect(sigc::mem_fun(this, &ManglerSettings::inputDeviceComboBox_changed_cb));
builder->get_widget("inputDeviceCustomName", inputDeviceCustomName);
builder->get_widget("outputDeviceComboBox", outputDeviceComboBox);
outputDeviceTreeModel = Gtk::ListStore::create(outputColumns);
outputDeviceComboBox->set_model(outputDeviceTreeModel);
outputDeviceComboBox->pack_start(outputColumns.description);
outputDeviceComboBox->signal_changed().connect(sigc::mem_fun(this, &ManglerSettings::outputDeviceComboBox_changed_cb));
builder->get_widget("outputDeviceCustomName", outputDeviceCustomName);
builder->get_widget("notificationDeviceComboBox", notificationDeviceComboBox);
notificationDeviceTreeModel = Gtk::ListStore::create(notificationColumns);
notificationDeviceComboBox->set_model(notificationDeviceTreeModel);
notificationDeviceComboBox->pack_start(notificationColumns.description);
notificationDeviceComboBox->signal_changed().connect(sigc::mem_fun(this, &ManglerSettings::notificationDeviceComboBox_changed_cb));
builder->get_widget("notificationDeviceCustomName", notificationDeviceCustomName);
mouseInputDevices = getInputDeviceList();
builder->get_widget("settingsMouseDeviceComboBox", mouseDeviceComboBox);
mouseDeviceTreeModel = Gtk::ListStore::create(mouseColumns);
mouseDeviceComboBox->set_model(mouseDeviceTreeModel);
mouseDeviceComboBox->pack_start(mouseColumns.name);
// Audio Subsystem
audioSubsystemTreeModel->clear();
Gtk::TreeModel::Row audioSubsystemRow;
#ifdef HAVE_PULSE
audioSubsystemRow = *(audioSubsystemTreeModel->append());
audioSubsystemRow[audioSubsystemColumns.id] = "pulse";
audioSubsystemRow[audioSubsystemColumns.name] = "PulseAudio";
#endif
#ifdef HAVE_ALSA
audioSubsystemRow = *(audioSubsystemTreeModel->append());
audioSubsystemRow[audioSubsystemColumns.id] = "alsa";
audioSubsystemRow[audioSubsystemColumns.name] = "ALSA";
#endif
#ifdef HAVE_OSS
audioSubsystemRow = *(audioSubsystemTreeModel->append());
audioSubsystemRow[audioSubsystemColumns.id] = "oss";
audioSubsystemRow[audioSubsystemColumns.name] = "OSS";
#endif
// Master Volume
volumeAdjustment = new Gtk::Adjustment(79, 0, 158, 1, 10, 10);
volumehscale = new Gtk::HScale(*volumeAdjustment);
volumehscale->add_mark(148, Gtk::POS_LEFT, "200%");
volumehscale->add_mark(79, Gtk::POS_LEFT, "100%");
volumehscale->add_mark(0, Gtk::POS_LEFT, "0%");
volumehscale->set_inverted(false);
volumehscale->set_draw_value(false);
builder->get_widget("masterVolumeVbox", vbox);
vbox->pack_start(*volumehscale);
volumehscale->show();
// Input Gain
gainAdjustment = new Gtk::Adjustment(79, 0, 158, 1, 10, 10);
gainhscale = new Gtk::HScale(*gainAdjustment);
gainhscale->add_mark(148, Gtk::POS_LEFT, "200%");
gainhscale->add_mark(79, Gtk::POS_LEFT, "100%");
gainhscale->add_mark(0, Gtk::POS_LEFT, "0%");
gainhscale->set_inverted(false);
gainhscale->set_draw_value(false);
builder->get_widget("inputGainVbox", vbox);
vbox->pack_start(*gainhscale);
gainhscale->show();
}/*}}}*/
void ManglerSettings::applySettings(void) {/*{{{*/
Gtk::TreeModel::iterator iter;
GdkWindow *rootwin = gdk_get_default_root_window();
// Key Push to Talk
builder->get_widget("settingsEnablePTTKeyCheckButton", checkbutton);
Mangler::config["PushToTalkKeyEnabled"] = checkbutton->get_active();
builder->get_widget("settingsPTTKeyValueLabel", label);
if (label->get_label() != PTT_KEY_GET && label->get_label() != PTT_KEY_SET) {
Mangler::config["PushToTalkKeyValue"] = label->get_text();
} else {
Mangler::config["PushToTalkKeyValue"] = "";
}
//Mangler::config.parsePushToTalkValue(config.PushToTalkKeyValue);
// Mouse Push to Talk
builder->get_widget("settingsMouseDeviceComboBox", combobox);
iter = combobox->get_active();
if (iter) {
Gtk::TreeModel::Row row = *iter;
Mangler::config["MouseDeviceName"] = Glib::ustring( row[mouseColumns.name] );
}
builder->get_widget("settingsEnablePTTMouseCheckButton", checkbutton);
Mangler::config["PushToTalkMouseEnabled"] = checkbutton->get_active();
builder->get_widget("settingsPTTMouseValueLabel", label);
if (label->get_label() != PTT_MOUSE_GET && label->get_label() != PTT_MOUSE_SET) {
Glib::ustring PushToTalkMouseValue = label->get_text();
if (PushToTalkMouseValue.length() > 6) {
Mangler::config["PushToTalkMouseValue"] = PushToTalkMouseValue.substr(6);
} else {
Mangler::config["PushToTalkMouseValue"] = PushToTalkMouseValue;
}
} else {
Mangler::config["PushToTalkMouseValue"] = "";
}
XUngrabButton(GDK_WINDOW_XDISPLAY(rootwin), AnyButton, AnyModifier, GDK_ROOT_WINDOW());
XAllowEvents (GDK_WINDOW_XDISPLAY(rootwin), AsyncBoth, CurrentTime);
/*
if (checkbutton->get_active()) {
XGrabButton(GDK_WINDOW_XDISPLAY(rootwin), config.PushToTalkMouseValueInt, AnyModifier, GDK_ROOT_WINDOW(), False, ButtonPressMask|ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None);
}
*/
// Audio Player Integration
builder->get_widget("settingsEnableAudioIntegrationCheckButton", checkbutton);
Mangler::config["AudioIntegrationEnabled"] = checkbutton->get_active();
iter = audioPlayerComboBox->get_active();
if (iter) {
Gtk::TreeModel::Row row = *iter;
uint8_t id = row[audioPlayerColumns.id];
Mangler::config["AudioIntegrationPlayer"] = id;
if (Mangler::config["AudioIntegrationEnabled"].toBool()) {
mangler->integration->setClient((MusicClient)id);
} else {
mangler->integration->setClient(MusicClient_None);
}
}
mangler->integration->update(true);
// Voice Activation
builder->get_widget("settingsEnableVoiceActivationCheckButton", checkbutton);
Mangler::config["VoiceActivationEnabled"] = checkbutton->get_active();
builder->get_widget("settingsVoiceActivationSilenceDurationSpinButton", spinbutton);
Mangler::config["VoiceActivationSilenceDuration"] = spinbutton->get_value() * 1000.0;
builder->get_widget("settingsVoiceActivationSensitivitySpinButton", spinbutton);
Mangler::config["VoiceActivationSensitivity"] = spinbutton->get_value_as_int();
#ifdef HAVE_XOSD
// On-Screen Display
builder->get_widget("settingsEnableOnScreenDisplayCheckButton", checkbutton);
Mangler::config["OnScreenDisplayEnabled"] = checkbutton->get_active();
if (checkbutton->get_active()) {
Gtk::TreeModel::iterator pos_iter = osdPosition->get_active();
if (pos_iter) {
int vert_pos_int = (*pos_iter)[osdPositionColumns.id];
Mangler::config["OnScreenDisplayVerticalPosition"] = vert_pos_int;
}
Gtk::TreeModel::iterator aln_iter = osdAlignment->get_active();
if (aln_iter) {
int horz_aln_int = (*aln_iter)[osdAlignmentColumns.id];
Mangler::config["OnScreenDisplayHorizontalAlignment"] = horz_aln_int;
}
Mangler::config["OnScreenDisplayFontSize"] = osdFontSize->get_value();
Gdk::Color color = osdColor->get_color();
char colorstr[16];
snprintf(colorstr, 15, "#%02x%02x%02x", color.get_red() / 256, color.get_green() / 256, color.get_blue() / 256);
Mangler::config["OnScreenDisplayColor"] = colorstr;
mangler->osd->destroyOsd();
}
#endif
// Audio Devices
iter = inputDeviceComboBox->get_active();
if (iter) {
Gtk::TreeModel::Row row = *iter;
Mangler::config["InputDeviceName"] = Glib::ustring( row[inputColumns.name] );
}
Mangler::config["InputDeviceCustomName"] = inputDeviceCustomName->get_text();
iter = outputDeviceComboBox->get_active();
if (iter) {
Gtk::TreeModel::Row row = *iter;
Mangler::config["OutputDeviceName"] = Glib::ustring( row[outputColumns.name] );
}
Mangler::config["OutputDeviceCustomName"] = outputDeviceCustomName->get_text();
iter = notificationDeviceComboBox->get_active();
if (iter) {
Gtk::TreeModel::Row row = *iter;
Mangler::config["NotificationDeviceName"] = Glib::ustring( row[notificationColumns.name] );
}
Mangler::config["NotificationDeviceCustomName"] = notificationDeviceCustomName->get_text();
iter = audioSubsystemComboBox->get_active();
if (iter) {
Gtk::TreeModel::Row row = *iter;
Mangler::config["AudioSubsystem"] = Glib::ustring( row[audioSubsystemColumns.id] );
}
// Master Volume
Mangler::config["MasterVolumeLevel"] = volumeAdjustment->get_value();
v3_set_volume_master(Mangler::config["MasterVolumeLevel"].toInt());
mangler->setTooltip();
// Input Gain
Mangler::config["InputGainLevel"] = gainAdjustment->get_value();
v3_set_volume_xmit(Mangler::config["InputGainLevel"].toInt());
// Notification Sounds
builder->get_widget("notificationLoginLogoutCheckButton", checkbutton);
Mangler::config["NotificationLoginLogout"] = checkbutton->get_active();
builder->get_widget("notificationChannelEnterLeaveCheckButton", checkbutton);
Mangler::config["NotificationChannelEnterLeave"] = checkbutton->get_active();
builder->get_widget("notificationTalkStartEndCheckButton", checkbutton);
Mangler::config["NotificationTransmitStartStop"] = checkbutton->get_active();
builder->get_widget("notificationTTSCheckButton", checkbutton);
Mangler::config["NotificationTextToSpeech"] = checkbutton->get_active();
// Debug Level
uint32_t debuglevel = 0;
builder->get_widget("debugStatus", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_STATUS : 0;
builder->get_widget("debugError", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_ERROR : 0;
builder->get_widget("debugStack", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_STACK : 0;
builder->get_widget("debugInternalNet", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_INTERNAL : 0;
builder->get_widget("debugPacketDump", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_PACKET : 0;
builder->get_widget("debugPacketParse", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_PACKET_PARSE : 0;
builder->get_widget("debugEventQueue", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_EVENT : 0;
builder->get_widget("debugSocket", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_SOCKET : 0;
builder->get_widget("debugNotice", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_NOTICE : 0;
builder->get_widget("debugInfo", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_INFO : 0;
builder->get_widget("debugMutex", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_MUTEX : 0;
builder->get_widget("debugMemory", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_MEMORY : 0;
builder->get_widget("debugEncryptedPacket", checkbutton);
debuglevel |= checkbutton->get_active() ? V3_DEBUG_PACKET_ENCRYPTED : 0;
Mangler::config["lv3_debuglevel"] = debuglevel;
v3_debuglevel(debuglevel);
Mangler::config.config.save();
}/*}}}*/
void ManglerSettings::initSettings(void) {/*{{{*/
// Key Push to Talk
builder->get_widget("settingsEnablePTTKeyCheckButton", checkbutton);
checkbutton->set_active(Mangler::config["PushToTalkKeyEnabled"].toBool());
builder->get_widget("settingsPTTKeyValueLabel", label);
if (Mangler::config["PushToTalkKeyValue"].length()) {
label->set_text(Mangler::config["PushToTalkKeyValue"].toUString());
} else {
label->set_markup(PTT_KEY_GET);
}
// Mouse Push to Talk
builder->get_widget("settingsEnablePTTMouseCheckButton", checkbutton);
checkbutton->set_active(Mangler::config["PushToTalkMouseEnabled"].toBool());
builder->get_widget("settingsPTTMouseValueLabel", label);
if (Mangler::config["PushToTalkMouseValue"].length()) {
label->set_text("Button" + Mangler::config["PushToTalkMouseValue"].toUString());
} else {
label->set_markup(PTT_MOUSE_GET);
}
// Audio Player Integration
builder->get_widget("settingsEnableAudioIntegrationCheckButton", checkbutton);
checkbutton->set_active(Mangler::config["AudioIntegrationEnabled"].toBool());
int audioPlayerSelection = 0;
int audioPlayerCtr = 0;
Gtk::TreeModel::Children apChildren = audioPlayerTreeModel->children();
for (Gtk::TreeModel::Children::iterator apIter = apChildren.begin();
apIter != apChildren.end();
++apIter, audioPlayerCtr++) {
Gtk::TreeModel::Row row = *apIter;
uint8_t id = row[audioPlayerColumns.id];
if (Mangler::config["AudioIntegrationPlayer"].toUInt() == id) {
audioPlayerSelection = audioPlayerCtr;
}
}
audioPlayerComboBox->set_active(audioPlayerSelection);
/*
iterate through whatever is available based on what we can find and populate the store
audioPlayerComboBox->set_active(iterOfSelectedinStore);
*/
// Voice Activation
builder->get_widget("settingsEnableVoiceActivationCheckButton", checkbutton);
checkbutton->set_active(Mangler::config["VoiceActivationEnabled"].toBool());
builder->get_widget("settingsVoiceActivationSilenceDurationSpinButton", spinbutton);
spinbutton->set_value(Mangler::config["VoiceActivationSilenceDuration"].toDouble() / 1000.0);
builder->get_widget("settingsVoiceActivationSensitivitySpinButton", spinbutton);
spinbutton->set_value(Mangler::config["VoiceActivationSensitivity"].toUInt());
#ifdef HAVE_XOSD
// On-Screen Display
builder->get_widget("settingsEnableOnScreenDisplayCheckButton", checkbutton);
checkbutton->set_active(Mangler::config["OnScreenDisplayEnabled"].toBool());
Gtk::TreeModel::iterator hz_iter = osdAlignmentModel->children().begin();
while (hz_iter != osdAlignmentModel->children().end()) {
int hzint = (*hz_iter)[osdAlignmentColumns.id];
if (Mangler::config["OnScreenDisplayHorizontalAlignment"].toInt() == hzint ||
(!Mangler::config["OnScreenDisplayHorizontalAlignment"].length() && hzint == XOSD_center)) {
osdAlignment->set_active(hz_iter);
break;
}
hz_iter++;
}
Gtk::TreeModel::iterator vt_iter = osdPositionModel->children().begin();
while (vt_iter != osdPositionModel->children().end()) {
int vtint = (*vt_iter)[osdPositionColumns.id];
if (Mangler::config["OnScreenDisplayVerticalPosition"].toInt() == vtint ||
(!Mangler::config["OnScreenDisplayVerticalPosition"].length() && vtint == XOSD_top)) {
osdPosition->set_active(vt_iter);
break;
}
vt_iter++;
}
if (Mangler::config["OnScreenDisplayFontSize"].length()) {
osdFontSize->set_value(Mangler::config["OnScreenDisplayFontSize"].toDouble());
} else {
osdFontSize->set_value(8.0);
}
if (Mangler::config["OnScreenDisplayColor"].length()) {
Gdk::Color color;
color.set(Mangler::config["OnScreenDisplayColor"].toUString());
osdColor->set_color(color);
}
#endif
// Audio Subsystem
for (Gtk::TreeModel::iterator asIter = audioSubsystemTreeModel->children().begin();
asIter != audioSubsystemTreeModel->children().end();
asIter++) {
if ((*asIter)[audioSubsystemColumns.id] == Mangler::config["AudioSubsystem"].toLower()) {
audioSubsystemComboBox->set_active(asIter);
}
}
// Audio Devices
inputDeviceCustomName->set_text(Mangler::config["InputDeviceCustomName"].toUString());
outputDeviceCustomName->set_text(Mangler::config["OutputDeviceCustomName"].toUString());
notificationDeviceCustomName->set_text(Mangler::config["NotificationDeviceCustomName"].toUString());
// Notification Sounds
builder->get_widget("notificationLoginLogoutCheckButton", checkbutton);
checkbutton->set_active(Mangler::config["NotificationLoginLogout"].toBool());
builder->get_widget("notificationChannelEnterLeaveCheckButton", checkbutton);
checkbutton->set_active(Mangler::config["NotificationChannelEnterLeave"].toBool());
builder->get_widget("notificationTalkStartEndCheckButton", checkbutton);
checkbutton->set_active(Mangler::config["NotificationTransmitStartStop"].toBool());
builder->get_widget("notificationTTSCheckButton", checkbutton);
checkbutton->set_active(Mangler::config["NotificationTextToSpeech"].toBool());
#ifdef HAVE_ESPEAK
checkbutton->set_sensitive(true);
#endif
// Master Volume
if (Mangler::config["MasterVolumeLevel"].length()) {
volumeAdjustment->set_value(Mangler::config["MasterVolumeLevel"].toInt());
}
// Input Gain
if (Mangler::config["InputGainLevel"].length()) {
gainAdjustment->set_value(Mangler::config["InputGainLevel"].toInt());
}
// Debug Level
builder->get_widget("debugStatus", checkbutton);
uint32_t config_lv3_debuglevel = Mangler::config["lv3_debuglevel"].toULong();
checkbutton->set_active(config_lv3_debuglevel & V3_DEBUG_STATUS ? 1 : 0);
builder->get_widget("debugError", checkbutton);
checkbutton->set_active(config_lv3_debuglevel & V3_DEBUG_ERROR ? 1 : 0);
builder->get_widget("debugStack", checkbutton);
checkbutton->set_active(config_lv3_debuglevel & V3_DEBUG_STACK ? 1 : 0);
builder->get_widget("debugInternalNet", checkbutton);
checkbutton->set_active(config_lv3_debuglevel & V3_DEBUG_INTERNAL ? 1 : 0);
builder->get_widget("debugPacketDump", checkbutton);
checkbutton->set_active(config_lv3_debuglevel & V3_DEBUG_PACKET ? 1 : 0);
builder->get_widget("debugPacketParse", checkbutton);
checkbutton->set_active(config_lv3_debuglevel & V3_DEBUG_PACKET_PARSE ? 1 : 0);
builder->get_widget("debugEventQueue", checkbutton);
checkbutton->set_active(config_lv3_debuglevel & V3_DEBUG_EVENT ? 1 : 0);
builder->get_widget("debugSocket", checkbutton);
checkbutton->set_active(config_lv3_debuglevel & V3_DEBUG_SOCKET ? 1 : 0);
builder->get_widget("debugNotice", checkbutton);
checkbutton->set_active(config_lv3_debuglevel & (uint32_t)V3_DEBUG_NOTICE ? 1 : 0);
builder->get_widget("debugInfo", checkbutton);
checkbutton->set_active(config_lv3_debuglevel & V3_DEBUG_INFO ? 1 : 0);
builder->get_widget("debugMutex", checkbutton);
checkbutton->set_active(config_lv3_debuglevel & V3_DEBUG_MUTEX ? 1 : 0);
builder->get_widget("debugMemory", checkbutton);
checkbutton->set_active(config_lv3_debuglevel & V3_DEBUG_MEMORY ? 1 : 0);
builder->get_widget("debugEncryptedPacket", checkbutton);
checkbutton->set_active(config_lv3_debuglevel & V3_DEBUG_PACKET_ENCRYPTED ? 1 : 0);
}/*}}}*/
// Settings Window Callbacks
void ManglerSettings::showSettingsWindow(void) {/*{{{*/
settingsWindow->show();
}/*}}}*/
void ManglerSettings::settingsWindow_show_cb(void) {/*{{{*/
Gtk::TreeModel::Row row;
isDetectingKey = false;
isDetectingMouse = false;
initSettings();
// these callbacks initialize the state
settingsEnablePTTKeyCheckButton_toggled_cb();
settingsEnablePTTMouseCheckButton_toggled_cb();
updateDeviceComboBoxes();
// Clear the mouse device store and rebuild it from the audioControl vector
mouseDeviceTreeModel->clear();
int mouseSelection = 0;
int mouseCtr = 0;
for (
std::map::iterator i = mouseInputDevices.begin();
i != mouseInputDevices.end();
i++, mouseCtr++) {
Gtk::TreeModel::Row row = *(mouseDeviceTreeModel->append());
row[mouseColumns.id] = (*i).first;
row[mouseColumns.name] = (*i).second;
if (Mangler::config["MouseDeviceName"] == (*i).second) {
mouseSelection = mouseCtr;
}
}
if (!mouseSelection) {
int mouseCtr = 0;
for (
std::map::iterator i = mouseInputDevices.begin();
i != mouseInputDevices.end();
i++, mouseCtr++) {
if ((*i).second.find("Mouse") != std::string::npos) {
mouseSelection = mouseCtr;
}
}
}
// TODO: get the currently selected item from settings object and select it
mouseDeviceComboBox->set_active(mouseSelection);
}/*}}}*/
void ManglerSettings::settingsWindow_hide_cb(void) {/*{{{*/
isDetectingKey = false;
isDetectingMouse = false;
}/*}}}*/
void ManglerSettings::settingsCancelButton_clicked_cb(void) {/*{{{*/
// additional cleanup should happen in ManglerSettings::settingsWindow_hide_cb()
settingsWindow->hide();
}/*}}}*/
void ManglerSettings::settingsApplyButton_clicked_cb(void) {/*{{{*/
applySettings();
}/*}}}*/
void ManglerSettings::settingsOkButton_clicked_cb(void) {/*{{{*/
applySettings();
settingsWindow->hide();
}/*}}}*/
void ManglerSettings::settingsEnablePTTKeyCheckButton_toggled_cb(void) {/*{{{*/
builder->get_widget("settingsEnablePTTKeyCheckButton", checkbutton);
if (checkbutton->get_active()) {
// box was checked
builder->get_widget("settingsPTTKeyLabel", label);
label->set_sensitive(true);
builder->get_widget("settingsPTTKeyValueLabel", label);
label->set_sensitive(true);
builder->get_widget("settingsPTTKeyButton", button);
button->set_sensitive(true);
} else {
// box was unchecked
builder->get_widget("settingsPTTKeyLabel", label);
label->set_sensitive(false);
builder->get_widget("settingsPTTKeyValueLabel", label);
label->set_sensitive(false);
builder->get_widget("settingsPTTKeyButton", button);
button->set_sensitive(false);
}
}/*}}}*/
void ManglerSettings::settingsEnableAudioIntegrationCheckButton_toggled_cb(void) {/*{{{*/
builder->get_widget("settingsEnableAudioIntegrationCheckButton", checkbutton);
if (checkbutton->get_active()) {
builder->get_widget("settingsAudioIntegrationLabel", label);
label->set_sensitive(true);
audioPlayerComboBox->set_sensitive(true);
} else {
builder->get_widget("settingsAudioIntegrationLabel", label);
label->set_sensitive(false);
audioPlayerComboBox->set_sensitive(false);
}
}/*}}}*/
void ManglerSettings::settingsEnableVoiceActivationCheckButton_toggled_cb(void) {/*{{{*/
builder->get_widget("settingsEnableVoiceActivationCheckButton", checkbutton);
if (checkbutton->get_active()) {
builder->get_widget("settingsVoiceActivationTable", table);
table->set_sensitive(true);
} else {
builder->get_widget("settingsVoiceActivationTable", table);
table->set_sensitive(false);
}
}/*}}}*/
void ManglerSettings::settingsEnableOnScreenDisplayCheckButton_toggled_cb(void) {/*{{{*/
builder->get_widget("settingsEnableOnScreenDisplayCheckButton", checkbutton);
builder->get_widget("settingsOSDTable", table);
table->set_sensitive(checkbutton->get_active());
}/*}}}*/
/*
* When this button is pressed, we need to disable all of the other items on
* the page until the user clicks the button again. This starts a timer to
* check keyboard state and update the settingsPTTKeyLabel to the key
* combination value. Setting isDetectingKey to false will cause the timer
* callback to stop running.
* The timer callback is ManglerSettings::settingsPTTKeyDetect.
*/
void ManglerSettings::settingsPTTKeyButton_clicked_cb(void) {/*{{{*/
builder->get_widget("settingsPTTKeyButton", button);
if (button->get_label() == "Set") {
isDetectingKey = true;
button->set_label("Done");
builder->get_widget("settingsCancelButton", button);
button->set_sensitive(false);
builder->get_widget("settingsApplyButton", button);
button->set_sensitive(false);
builder->get_widget("settingsOkButton", button);
button->set_sensitive(false);
Glib::signal_timeout().connect( sigc::mem_fun(*this, &ManglerSettings::settingsPTTKeyDetect), 100 );
} else {
isDetectingKey = false;
button->set_label("Set");
builder->get_widget("settingsCancelButton", button);
button->set_sensitive(true);
builder->get_widget("settingsApplyButton", button);
button->set_sensitive(true);
builder->get_widget("settingsOkButton", button);
button->set_sensitive(true);
builder->get_widget("settingsPTTKeyValueLabel", label);
// if the text is as follows, the user pressed done without any keys
// pressed down and reset it to the default text
if (label->get_label() == PTT_KEY_SET) {
label->set_markup(PTT_KEY_GET);
}
}
}/*}}}*/
void ManglerSettings::settingsEnablePTTMouseCheckButton_toggled_cb(void) {/*{{{*/
builder->get_widget("settingsEnablePTTMouseCheckButton", checkbutton);
if (checkbutton->get_active()) {
// box was checked
builder->get_widget("settingsPTTMouseLabel", label);
label->set_sensitive(true);
builder->get_widget("settingsPTTMouseValueLabel", label);
label->set_sensitive(true);
builder->get_widget("settingsPTTMouseButton", button);
button->set_sensitive(true);
builder->get_widget("settingsMouseDeviceLabel", label);
label->set_sensitive(true);
builder->get_widget("settingsMouseDeviceComboBox", combobox);
combobox->set_sensitive(true);
} else {
// box was unchecked
builder->get_widget("settingsPTTMouseLabel", label);
label->set_sensitive(false);
builder->get_widget("settingsPTTMouseValueLabel", label);
label->set_sensitive(false);
builder->get_widget("settingsPTTMouseButton", button);
button->set_sensitive(false);
builder->get_widget("settingsMouseDeviceLabel", label);
label->set_sensitive(false);
builder->get_widget("settingsMouseDeviceComboBox", combobox);
combobox->set_sensitive(false);
}
}/*}}}*/
void ManglerSettings::settingsPTTMouseButton_clicked_cb(void) {/*{{{*/
isDetectingMouse = true;
builder->get_widget("settingsPTTMouseValueLabel", label);
label->set_markup(PTT_MOUSE_SET);
builder->get_widget("settingsPTTMouseButton", button);
button->set_sensitive(false);
builder->get_widget("settingsCancelButton", button);
button->set_sensitive(false);
builder->get_widget("settingsApplyButton", button);
button->set_sensitive(false);
builder->get_widget("settingsOkButton", button);
button->set_sensitive(false);
builder->get_widget("settingsMouseDeviceComboBox", combobox);
combobox->set_sensitive(false);
Glib::signal_timeout().connect( sigc::mem_fun(*this, &ManglerSettings::settingsPTTMouseDetect), 100 );
}/*}}}*/
std::map ManglerSettings::getInputDeviceList(void) {/*{{{*/
GdkWindow *rootwin = gdk_get_default_root_window();
XDeviceInfo *xdev;
int ndevices_return;
std::map devicelist;
xdev = XListInputDevices(GDK_WINDOW_XDISPLAY(rootwin), &ndevices_return);
for (int ctr = 0; ctr < ndevices_return; ctr++) {
if (xdev[ctr].use == IsXExtensionPointer) {
devicelist[xdev[ctr].id] = xdev[ctr].name;
}
}
XFreeDeviceList(xdev);
return(devicelist);
}/*}}}*/
void ManglerSettings::audioSubsystemComboBox_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter;
iter = audioSubsystemComboBox->get_active();
if (iter) {
Gtk::TreeModel::Row row = *iter;
Glib::ustring id = row[audioSubsystemColumns.id];
Glib::ustring name = row[audioSubsystemColumns.name];
if (mangler) {
mangler->audioControl->getDeviceList(id);
updateDeviceComboBoxes();
}
}
}/*}}}*/
bool
ManglerSettings::settingsPTTKeyDetect(void) {/*{{{*/
char pressed_keys[32];
Glib::ustring ptt_keylist;
GdkWindow *rootwin = gdk_get_default_root_window();
// TODO: window close event needs to set isDetectingKey
if (!isDetectingKey) {
return false;
}
/*
* Query the X keymap and get a list of all the keys are pressed. Convert
* keycodes to keysyms to keynames and build a human readable string that
* will be the actual value stored in the settings file
*/
XQueryKeymap(GDK_WINDOW_XDISPLAY(rootwin), pressed_keys);
for (int ctr = 0; ctr < 256; ctr++) {
if ((pressed_keys[ctr >> 3] >> (ctr & 0x07)) & 0x01) {
char *keystring = XKeysymToString(XKeycodeToKeysym(GDK_WINDOW_XDISPLAY(rootwin), ctr, 0));
if (keystring == NULL)
continue;
std::string keyname = keystring;
if (keyname.length() > 1) {
ptt_keylist.insert(0, "<" + keyname + ">" + (ptt_keylist.empty() ? "" : "+"));
} else {
keyname[0] = toupper(keyname[0]);
ptt_keylist.append((ptt_keylist.empty() ? "" : "+") + keyname);
}
}
}
builder->get_widget("settingsPTTKeyValueLabel", label);
if (ptt_keylist.empty()) {
label->set_markup(PTT_KEY_SET);
} else {
label->set_text(ptt_keylist);
}
return(true);
}/*}}}*/
bool
ManglerSettings::settingsPTTMouseDetect(void) {/*{{{*/
GdkWindow *rootwin = gdk_get_default_root_window();
Glib::ustring buttonname;
char mousebutton[8];
static bool grabbed = false;
int flag = 0;
//int x, y;
XEvent ev;
// TODO: window close event needs to set isDetectingKey
if (!isDetectingMouse) {
return false;
}
if (! grabbed) {
XUngrabPointer(GDK_WINDOW_XDISPLAY(rootwin), CurrentTime);
XGrabPointer(GDK_WINDOW_XDISPLAY(rootwin), GDK_ROOT_WINDOW(), False, ButtonPress, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
grabbed = true;
}
while (flag == 0) {
while (!XPending(GDK_WINDOW_XDISPLAY(rootwin))) {
usleep(100000);
}
XNextEvent(GDK_WINDOW_XDISPLAY(rootwin), &ev);
switch (ev.type) {
case ButtonPress:
snprintf(mousebutton, 7, "%d", ev.xbutton.button);
buttonname = "Button" + Glib::ustring(mousebutton);
flag = 1;
XUngrabPointer(GDK_WINDOW_XDISPLAY(rootwin), CurrentTime);
grabbed = false;
isDetectingMouse = false;
//x = ev.xbutton.x_root;
//y = ev.xbutton.y_root;
break;
case MotionNotify:
break;
default:
break;
}
XAllowEvents(GDK_WINDOW_XDISPLAY(rootwin), AsyncBoth, CurrentTime);
}
isDetectingMouse = false;
builder->get_widget("settingsPTTMouseValueLabel", label);
label->set_markup(buttonname);
builder->get_widget("settingsCancelButton", button);
button->set_sensitive(true);
builder->get_widget("settingsApplyButton", button);
button->set_sensitive(true);
builder->get_widget("settingsOkButton", button);
button->set_sensitive(true);
builder->get_widget("settingsOkButton", button);
button->set_sensitive(true);
builder->get_widget("settingsPTTMouseButton", button);
button->set_sensitive(true);
builder->get_widget("settingsMouseDeviceComboBox", combobox);
combobox->set_sensitive(true);
return(true);
}/*}}}*/
void
ManglerSettings::updateDeviceComboBoxes(void) {/*{{{*/
Gtk::TreeModel::Row row;
Gtk::TreeModel::iterator iter;
// Clear the input device store and rebuild it from the audioControl vector
inputDeviceTreeModel->clear();
row = *(inputDeviceTreeModel->append());
row[inputColumns.id] = -1;
row[inputColumns.name] = "Default";
row[inputColumns.description] = "Default";
int inputSelection = 0;
int inputCtr = 1;
for (
std::vector::iterator i = mangler->audioControl->inputDevices.begin();
i < mangler->audioControl->inputDevices.end();
i++, inputCtr++) {
Gtk::TreeModel::Row row = *(inputDeviceTreeModel->append());
row[inputColumns.id] = (*i)->id;
row[inputColumns.name] = (*i)->name;
row[inputColumns.description] = (*i)->description;
if (Mangler::config["InputDeviceName"] == (*i)->name) {
inputSelection = inputCtr;
}
}
iter = audioSubsystemComboBox->get_active();
if (iter && (*iter)[audioSubsystemColumns.id] != "pulse") {
row = *(inputDeviceTreeModel->append());
row[inputColumns.id] = -2;
row[inputColumns.name] = "Custom";
row[inputColumns.description] = "Custom";
if (Mangler::config["InputDeviceName"] == "Custom") {
inputSelection = inputCtr;
}
}
// TODO: get the currently selected item from settings object and select it
inputDeviceComboBox->set_active(inputSelection);
// Clear the output device store and rebuild it from the audioControl vector
outputDeviceTreeModel->clear();
row = *(outputDeviceTreeModel->append());
row[outputColumns.id] = -1;
row[outputColumns.name] = "Default";
row[outputColumns.description] = "Default";
int outputSelection = 0;
int outputCtr = 1;
for (
std::vector::iterator i = mangler->audioControl->outputDevices.begin();
i < mangler->audioControl->outputDevices.end();
i++, outputCtr++) {
Gtk::TreeModel::Row row = *(outputDeviceTreeModel->append());
row[outputColumns.id] = (*i)->id;
row[outputColumns.name] = (*i)->name;
row[outputColumns.description] = (*i)->description;
if (Mangler::config["OutputDeviceName"] == (*i)->name) {
outputSelection = outputCtr;
}
}
iter = audioSubsystemComboBox->get_active();
if (iter && (*iter)[audioSubsystemColumns.id] != "pulse") {
row = *(outputDeviceTreeModel->append());
row[outputColumns.id] = -2;
row[outputColumns.name] = "Custom";
row[outputColumns.description] = "Custom";
if (Mangler::config["OutputDeviceName"] == "Custom") {
outputSelection = outputCtr;
}
}
// TODO: get the currently selected item from settings object and select it
outputDeviceComboBox->set_active(outputSelection);
// Clear the notification device store and rebuild it from the audioControl vector
notificationDeviceTreeModel->clear();
row = *(notificationDeviceTreeModel->append());
row[notificationColumns.id] = -1;
row[notificationColumns.name] = "Default";
row[notificationColumns.description] = "Default";
int notificationSelection = 0;
int notificationCtr = 1;
for (
std::vector::iterator i = mangler->audioControl->outputDevices.begin();
i < mangler->audioControl->outputDevices.end();
i++, notificationCtr++) {
Gtk::TreeModel::Row row = *(notificationDeviceTreeModel->append());
row[notificationColumns.id] = (*i)->id;
row[notificationColumns.name] = (*i)->name;
row[notificationColumns.description] = (*i)->description;
if (Mangler::config["NotificationDeviceName"] == (*i)->name) {
notificationSelection = notificationCtr;
}
}
iter = audioSubsystemComboBox->get_active();
if (iter && (*iter)[audioSubsystemColumns.id] != "pulse") {
row = *(notificationDeviceTreeModel->append());
row[notificationColumns.id] = -2;
row[notificationColumns.name] = "Custom";
row[notificationColumns.description] = "Custom";
if (Mangler::config["NotificationDeviceName"] == "Custom") {
notificationSelection = notificationCtr;
}
}
// TODO: get the currently selected item from settings object and select it
notificationDeviceComboBox->set_active(notificationSelection);
}/*}}}*/
void
ManglerSettings::inputDeviceComboBox_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = inputDeviceComboBox->get_active();
builder->get_widget("CustomInputLabel", label);
if (iter && (*iter)[inputColumns.id] == -2) {
inputDeviceCustomName->show();
label->show();
return;
}
inputDeviceCustomName->hide();
label->hide();
}/*}}}*/
void
ManglerSettings::outputDeviceComboBox_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = outputDeviceComboBox->get_active();
builder->get_widget("CustomOutputLabel", label);
if (iter && (*iter)[outputColumns.id] == -2) {
outputDeviceCustomName->show();
label->show();
return;
}
outputDeviceCustomName->hide();
label->hide();
}/*}}}*/
void
ManglerSettings::notificationDeviceComboBox_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = notificationDeviceComboBox->get_active();
builder->get_widget("CustomNotificationLabel", label);
if (iter && (*iter)[notificationColumns.id] == -2) {
notificationDeviceCustomName->show();
label->show();
return;
}
notificationDeviceCustomName->hide();
label->hide();
}/*}}}*/
mangler-1.2.5/src/._manglersettings.cpp 0000644 0000765 0000062 00000000336 11757473570 016050 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerserverlist.h 0000644 0000765 0000062 00000010216 11602153752 015622 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerserverlist.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLERSERVERLIST_H
#define _MANGLERSERVERLIST_H
class ManglerServerList {
public:
ManglerServerList(Glib::RefPtr builder);
Gtk::Window *serverListWindow;
class serverListModelColumns : public Gtk::TreeModel::ColumnRecord {
public:
serverListModelColumns() { add(id); add(name); add(hostname); add(port); add(username); }
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn name;
Gtk::TreeModelColumn hostname;
Gtk::TreeModelColumn port;
Gtk::TreeModelColumn username;
};
serverListModelColumns serverListColumns;
Glib::RefPtr serverListTreeModel;
Gtk::TreeView *serverListView;
Glib::RefPtr serverListSelection;
// Table fields
Gtk::Table *serverListServerTable;
Gtk::Table *serverListUserTable;
Gtk::Table *serverListOptionsTable;
// Entry fields
std::string editorName;
int32_t editorId;
Gtk::Entry *serverListServerNameEntry;
Gtk::Entry *serverListHostnameEntry;
Gtk::Entry *serverListPortEntry;
Gtk::Entry *serverListDefaultChannelEntry;
Gtk::Entry *serverListUsernameEntry;
Gtk::Entry *serverListPasswordEntry;
Gtk::Entry *serverListPhoneticEntry;
Gtk::Entry *serverListCommentEntry;
// CheckButton fields
Gtk::CheckButton *serverListPageCheckButton;
Gtk::CheckButton *serverListUtUCheckButton;
Gtk::CheckButton *serverListPrivateChatCheckButton;
Gtk::CheckButton *serverListRecordCheckButton;
Gtk::CheckButton *serverListPersistentConnectionCheckButton;
Gtk::CheckButton *serverListPersistentCommentsCheckButton;
// Character Set Combobox
Gtk::ComboBoxEntry *serverListCharsetComboBox;
class charsetModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
charsetModelColumns() { add(name); }
Gtk::TreeModelColumn name;
};
charsetModelColumns charsetColumns;
Glib::RefPtr charsetTreeModel;
// Editor Buttons
Gtk::Button *serverListServerUpdateButton;
Gtk::Button *serverListServerAddButton;
Gtk::Button *serverListServerRemoveButton;
Gtk::Button *serverListServerCloneButton;
void serverListWindow_hide_cb(void);
void serverListSelection_changed_cb(void);
void serverListAddButton_clicked_cb(void);
void serverListRemoveButton_clicked_cb(void);
void serverListCloneButton_clicked_cb(void);
void serverListCloseButton_clicked_cb(void);
void serverListServerUpdateButton_clicked_cb(void);
void editRow(const std::string &name);
void saveRow();
void clearEntries(void);
void queue_resize(void);
Glib::ustring trim(Glib::ustring const& orig);
// generic types for builder
Gtk::Button *button;
};
#endif
mangler-1.2.5/src/._manglerserverlist.h 0000644 0000765 0000062 00000000336 11602153752 016041 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerserverlist.cpp 0000644 0000765 0000062 00000033550 11602153752 016163 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerserverlist.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#include "manglerserverlist.h"
#include "manglersettings.h"
#include "manglercharset.h"
ManglerServerList::ManglerServerList(Glib::RefPtr builder) {
serverListTreeModel = Gtk::ListStore::create(serverListColumns);
builder->get_widget("serverListWindow", serverListWindow);
serverListWindow->signal_hide().connect(sigc::mem_fun(this, &ManglerServerList::serverListWindow_hide_cb));
builder->get_widget("serverListView", serverListView);
serverListView->set_model(serverListTreeModel);
serverListView->append_column("Name", serverListColumns.name);
serverListView->get_column(0)->set_sort_column(serverListColumns.name);
serverListView->append_column("Username", serverListColumns.username);
serverListView->get_column(1)->set_sort_column(serverListColumns.username);
serverListView->append_column("Hostname", serverListColumns.hostname);
serverListView->get_column(2)->set_sort_column(serverListColumns.hostname);
serverListView->append_column("Port", serverListColumns.port);
serverListView->get_column(3)->set_sort_column(serverListColumns.port);
serverListSelection = serverListView->get_selection();
serverListSelection->signal_changed().connect(sigc::mem_fun(this, &ManglerServerList::serverListSelection_changed_cb));
builder->get_widget("serverListAddButton", serverListServerAddButton);
serverListServerAddButton->signal_clicked().connect(sigc::mem_fun(this, &ManglerServerList::serverListAddButton_clicked_cb));
builder->get_widget("serverListRemoveButton", serverListServerRemoveButton);
serverListServerRemoveButton->signal_clicked().connect(sigc::mem_fun(this, &ManglerServerList::serverListRemoveButton_clicked_cb));
builder->get_widget("serverListCloneButton", serverListServerCloneButton);
serverListServerCloneButton->signal_clicked().connect(sigc::mem_fun(this, &ManglerServerList::serverListCloneButton_clicked_cb));
builder->get_widget("serverListCloseButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerServerList::serverListCloseButton_clicked_cb));
builder->get_widget("serverListServerUpdateButton", serverListServerUpdateButton);
serverListServerUpdateButton->signal_clicked().connect(sigc::mem_fun(this, &ManglerServerList::serverListServerUpdateButton_clicked_cb));
builder->get_widget("serverListServerTable", serverListServerTable);
builder->get_widget("serverListUserTable", serverListUserTable);
builder->get_widget("serverListOptionsTable", serverListOptionsTable);
builder->get_widget("serverListServerNameEntry", serverListServerNameEntry);
builder->get_widget("serverListHostnameEntry", serverListHostnameEntry);
builder->get_widget("serverListPortEntry", serverListPortEntry);
builder->get_widget("serverListDefaultChannelEntry", serverListDefaultChannelEntry);
builder->get_widget("serverListUsernameEntry", serverListUsernameEntry);
builder->get_widget("serverListPasswordEntry", serverListPasswordEntry);
builder->get_widget("serverListPhoneticEntry", serverListPhoneticEntry);
builder->get_widget("serverListCommentEntry", serverListCommentEntry);
// CheckButton fields
builder->get_widget("serverListPageCheckButton", serverListPageCheckButton);
builder->get_widget("serverListUtUCheckButton", serverListUtUCheckButton);
builder->get_widget("serverListPrivateChatCheckButton", serverListPrivateChatCheckButton);
builder->get_widget("serverListRecordCheckButton", serverListRecordCheckButton);
builder->get_widget("serverListPersistentConnectionCheckButton", serverListPersistentConnectionCheckButton);
builder->get_widget("serverListPersistentCommentsCheckButton", serverListPersistentCommentsCheckButton);
// Charset combobox
builder->get_widget("serverListCharsetComboBox", serverListCharsetComboBox);
charsetTreeModel = Gtk::ListStore::create(charsetColumns);
serverListCharsetComboBox->set_model(charsetTreeModel);
serverListCharsetComboBox->set_text_column(charsetColumns.name);
for (int ctr = 0; charsetslist[ctr] != NULL; ctr++) {
Gtk::TreeModel::Row charsetRow = *(charsetTreeModel->append());
charsetRow[charsetColumns.name] = charsetslist[ctr];
}
serverListCharsetComboBox->get_entry()->set_text("");
editorName = "";
}
void ManglerServerList::serverListWindow_hide_cb(void) {
clearEntries();
}
void ManglerServerList::serverListSelection_changed_cb(void) {
Gtk::TreeModel::iterator iter = serverListSelection->get_selected();
if (iter) {
Gtk::TreeModel::Row row = *iter;
editorName = Glib::locale_from_utf8(row[serverListColumns.name]);
editRow(editorName);
serverListServerAddButton->set_sensitive(true);
serverListServerRemoveButton->set_sensitive(true);
serverListServerCloneButton->set_sensitive(true);
} else {
serverListServerRemoveButton->set_sensitive(false);
serverListServerCloneButton->set_sensitive(false);
}
}
void ManglerServerList::serverListRemoveButton_clicked_cb(void) {
Gtk::TreeModel::iterator iter = serverListSelection->get_selected();
if (!iter) {
return;
}
Gtk::TreeModel::Row row = *iter;
Glib::ustring name = row[serverListColumns.name];
Mangler::config.servers.erase(name);
Mangler::config.servers.save();
serverListTreeModel->erase(row);
editorName = "";
clearEntries();
queue_resize();
}
void ManglerServerList::serverListCloneButton_clicked_cb(void) {
Gtk::TreeModel::iterator curIter = serverListSelection->get_selected();
if (!curIter) {
return; // should never happen
}
serverListServerAddButton->set_sensitive(false);
Glib::ustring server_name = (*curIter)[serverListColumns.name];
editorName = "";
editRow(server_name);
}
void ManglerServerList::clearEntries(void) {
serverListSelection->unselect_all();
serverListServerNameEntry->set_text("");
serverListHostnameEntry->set_text("");
serverListPortEntry->set_text("");
serverListDefaultChannelEntry->set_text("");
serverListUsernameEntry->set_text("");
serverListPasswordEntry->set_text("");
serverListPhoneticEntry->set_text("");
serverListCommentEntry->set_text("");
serverListPageCheckButton->set_active(false);
serverListUtUCheckButton->set_active(false);
serverListPrivateChatCheckButton->set_active(false);
serverListRecordCheckButton->set_active(false);
serverListPersistentConnectionCheckButton->set_active(false);
serverListPersistentCommentsCheckButton->set_active(false);
serverListCharsetComboBox->get_entry()->set_text("");
serverListServerTable->set_sensitive(false);
serverListUserTable->set_sensitive(false);
serverListOptionsTable->set_sensitive(false);
serverListServerUpdateButton->set_sensitive(false);
serverListServerAddButton->set_sensitive(true);
serverListServerRemoveButton->set_sensitive(false);
serverListServerCloneButton->set_sensitive(false);
}
void ManglerServerList::queue_resize(void) {
for (int ctr = 0, cnt = serverListView->get_columns().size(); ctr < cnt; ctr++) {
serverListView->get_column(ctr)->queue_resize();
}
}
void ManglerServerList::serverListAddButton_clicked_cb(void) {
serverListServerAddButton->set_sensitive(false);
editorName = "";
editRow("");
}
void ManglerServerList::serverListCloseButton_clicked_cb(void) {
serverListWindow->hide();
}
void ManglerServerList::serverListServerUpdateButton_clicked_cb(void) {
saveRow();
}
void ManglerServerList::editRow(const std::string &name) {
if (editorName.empty()) {
serverListSelection->unselect_all();
}
serverListServerTable->set_sensitive(true);
serverListUserTable->set_sensitive(true);
serverListOptionsTable->set_sensitive(true);
serverListServerUpdateButton->set_sensitive(true);
serverListServerCloneButton->set_sensitive(! editorName.empty());
serverListServerRemoveButton->set_sensitive(! editorName.empty());
serverListServerNameEntry->grab_focus();
iniSection server;
if (name.length()) {
server = Mangler::config.servers[name];
}
serverListServerNameEntry->set_text(name);
serverListHostnameEntry->set_text(server["Hostname"].toUString());
serverListPortEntry->set_text(server["Port"].toUString());
serverListDefaultChannelEntry->set_text(server["DefaultChannel"].toUString());
serverListUsernameEntry->set_text(server["Username"].toUString());
serverListPasswordEntry->set_text(server["Password"].toUString());
serverListPhoneticEntry->set_text(server["Phonetic"].toUString());
serverListCommentEntry->set_text(server["Comment"].toUString());
serverListPageCheckButton->set_active(
server["AcceptPages"].length() ?
server["AcceptPages"].toBool() : true);
serverListUtUCheckButton->set_active(
server["AcceptU2U"].length() ?
server["AcceptU2U"].toBool() : true);
serverListPrivateChatCheckButton->set_active(
server["AcceptPrivateChat"].length() ?
server["AcceptPrivateChat"].toBool() : true);
serverListRecordCheckButton->set_active(
server["AllowRecording"].length() ?
server["AllowRecording"].toBool() : true);
serverListPersistentConnectionCheckButton->set_active(
server["PersistentConnection"].length() ?
server["PersistentConnection"].toBool() : true);
serverListPersistentCommentsCheckButton->set_active(
server["PersistentComments"].length() ?
server["PersistentComments"].toBool() : true);
std::string server_charset = server["Charset"].toString();
if (server_charset.empty()) {
server_charset = charsetslist[0];
}
serverListCharsetComboBox->get_entry()->set_text(server_charset);
}
void ManglerServerList::saveRow() {
Glib::ustring charset;
Gtk::TreeModel::iterator curIter = serverListSelection->get_selected();
if (editorName.length() && !curIter) {
return; // should never happen
}
Glib::ustring server_name = trim(serverListServerNameEntry->get_text());
if (server_name.empty()) {
mangler->errorDialog("Cannot save server without a name.");
return;
}
// check for duplicate
Gtk::TreeModel::Children::iterator ckIter = serverListTreeModel->children().begin();
while (ckIter != serverListTreeModel->children().end()) {
if ((editorName.empty() || ckIter != curIter) && (*ckIter)[serverListColumns.name] == server_name) {
mangler->errorDialog("Server names must be unique.");
return;
}
ckIter++;
}
// if name changed, remove old section first
if (editorName.length() && server_name != editorName) {
Mangler::config.servers.erase(editorName);
}
// save to config
iniSection &server( Mangler::config.servers[server_name] );
server["Hostname"] = trim(serverListHostnameEntry->get_text());
server["Port"] = trim(serverListPortEntry->get_text());
server["DefaultChannel"] = trim(serverListDefaultChannelEntry->get_text());
server["Username"] = trim(serverListUsernameEntry->get_text());
server["Password"] = trim(serverListPasswordEntry->get_text());
server["Phonetic"] = trim(serverListPhoneticEntry->get_text());
server["Comment"] = trim(serverListCommentEntry->get_text());
server["AcceptPages"] = serverListPageCheckButton->get_active();
server["AcceptU2U"] = serverListUtUCheckButton->get_active();
server["AcceptPrivateChat"] = serverListPrivateChatCheckButton->get_active();
server["AllowRecording"] = serverListRecordCheckButton->get_active();
server["PersistentConnection"] = serverListPersistentConnectionCheckButton->get_active();
server["PersistentComments"] = serverListPersistentCommentsCheckButton->get_active();
server["Charset"] = serverListCharsetComboBox->get_active_text();
Gtk::TreeModel::Row row = (editorName.empty()) ? *(serverListTreeModel->append()) : *curIter;
row[serverListColumns.name] = server_name;
row[serverListColumns.hostname] = server["Hostname"].toUString();
row[serverListColumns.port] = server["Port"].toUString();
row[serverListColumns.username] = server["Username"].toUString();
queue_resize();
if (editorName.empty()) {
serverListView->set_cursor(serverListTreeModel->get_path(row));
}
editorName = server_name;
Mangler::config.servers.save();
}
Glib::ustring ManglerServerList::trim(Glib::ustring const& orig) {
char const blankChars[] = " \t\n\r";
Glib::ustring::size_type const first = orig.find_first_not_of(blankChars);
return ( first==Glib::ustring::npos )
? Glib::ustring()
: orig.substr(first, orig.find_last_not_of(blankChars)-first+1);
}
mangler-1.2.5/src/._manglerserverlist.cpp 0000644 0000765 0000062 00000000336 11602153752 016374 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerrecorder.h 0000644 0000765 0000062 00000011037 11602153752 015227 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerrecorder.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLERRECORDER_H
#define _MANGLERRECORDER_H
class ManglerRecorder {
public:
ManglerRecorder(Glib::RefPtr builder);
~ManglerRecorder();
Glib::RefPtr builder;
Gtk::Window *recWindow;
Gtk::Dialog *recInfoDialog;
Gtk::ScrolledWindow *recScrolledWindow;
Gtk::MenuItem *menuitem;
Gtk::Button *button;
Gtk::Label *label;
Gtk::Entry *entry;
Gtk::Widget *widget;
Gtk::ToggleButton *recordbutton;
Gtk::Entry *fileentry;
Gtk::FileChooserDialog *filedialog;
Gtk::TextView *textview;
bool isPlaying;
bool isRecording;
void show(void);
void can_record(bool isConnected);
void record(Glib::ustring username, Glib::ustring text, uint32_t index, uint32_t time, bool stopped, bool flushed);
protected:
Glib::ustring recdir;
void *vrfh;
Glib::ustring path;
Glib::ustring filename;
uint32_t totalduration;
Glib::Thread *player;
class recModelColumns : public Gtk::TreeModel::ColumnRecord {
public:
recModelColumns() {
add(id);
add(time_val);
add(duration_val);
add(diff_val);
add(time);
add(duration);
add(status);
add(username);
add(text);
}
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn time_val;
Gtk::TreeModelColumn duration_val;
Gtk::TreeModelColumn diff_val;
Gtk::TreeModelColumn time;
Gtk::TreeModelColumn duration;
Gtk::TreeModelColumn status;
Gtk::TreeModelColumn username;
Gtk::TreeModelColumn text;
} recRecord;
Glib::RefPtr recListModel;
Gtk::TreeView *recListTree;
class ManglerRecorderData {
public:
ManglerRecorderData(v3_vrf_data *vrfd = NULL) {
this->vrfd = vrfd;
next = 0;
outputAudio = NULL;
}
v3_vrf_data *vrfd;
double next;
ManglerAudio *outputAudio;
};
void hide_activate_cb(void);
void open_activate_cb(void);
void close_activate_cb(void);
void saveas_activate_cb(void);
void delete_activate_cb(void);
void playpause_clicked_cb(void);
void stop_clicked_cb(void);
void record_toggled_cb(void);
void info_clicked_cb(void);
void recListTree_cursor_changed_cb(void);
void recListTree_row_activated_cb(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column);
void set(bool isRecording);
void reset(bool destroying = false);
void play(void);
void recInfoDialog_cancel_clicked_cb(void);
void recInfoDialog_save_clicked_cb(void);
Glib::ustring float_to_ustring(float val, int precision = 2);
Glib::ustring bytes_to_readable(double size);
Glib::ustring msec_to_timestamp(uint32_t milliseconds);
Glib::ustring timestamp(Glib::ustring format = "%Y%m%d-%H%M%S");
};
#endif
mangler-1.2.5/src/._manglerrecorder.h 0000644 0000765 0000062 00000000336 11602153752 015444 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerrecorder.cpp 0000644 0000765 0000062 00000053624 11602153752 015572 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerrecorder.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#include "manglerrecorder.h"
#include "mangleraudio.h"
#include "manglercharset.h"
#include
#include
#include
ManglerRecorder::ManglerRecorder(Glib::RefPtr builder) {/*{{{*/
this->builder = builder;
builder->get_widget("recWindow", recWindow);
builder->get_widget("recHide", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &ManglerRecorder::hide_activate_cb));
builder->get_widget("recOpen", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &ManglerRecorder::open_activate_cb));
builder->get_widget("recClose", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &ManglerRecorder::close_activate_cb));
builder->get_widget("recSaveAs", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &ManglerRecorder::saveas_activate_cb));
builder->get_widget("recDelete", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &ManglerRecorder::delete_activate_cb));
builder->get_widget("recPlayPause", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerRecorder::playpause_clicked_cb));
builder->get_widget("recStop", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerRecorder::stop_clicked_cb));
builder->get_widget("recRecord", recordbutton);
recordbutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerRecorder::record_toggled_cb));
builder->get_widget("recInfo", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerRecorder::info_clicked_cb));
builder->get_widget("recOpenEntry", fileentry);
builder->get_widget("recOpenButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerRecorder::open_activate_cb));
filedialog = new Gtk::FileChooserDialog("Open Recording", Gtk::FILE_CHOOSER_ACTION_OPEN);
filedialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
filedialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
Gtk::FileFilter vrf_filter;
vrf_filter.set_name("Ventrilo Recording File (*.vrf)");
vrf_filter.add_pattern("*.vrf");
filedialog->add_filter(vrf_filter);
Gtk::FileFilter all_filter;
all_filter.set_name("All Files");
all_filter.add_pattern("*");
filedialog->add_filter(all_filter);
builder->get_widget("recScrolledWindow", recScrolledWindow);
recListModel = Gtk::ListStore::create(recRecord);
builder->get_widget("recListTree", recListTree);
recListTree->set_model(recListModel);
recListTree->append_column("Time", recRecord.time);
recListTree->append_column("Duration", recRecord.duration);
recListTree->append_column("Status", recRecord.status);
recListTree->append_column("Username", recRecord.username);
recListTree->append_column("", recRecord.text);
recListTree->signal_cursor_changed().connect(sigc::mem_fun(this, &ManglerRecorder::recListTree_cursor_changed_cb));
recListTree->signal_row_activated().connect(sigc::mem_fun(this, &ManglerRecorder::recListTree_row_activated_cb));
builder->get_widget("recInfoDialog", recInfoDialog);
builder->get_widget("recInfoCancel", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerRecorder::recInfoDialog_cancel_clicked_cb));
builder->get_widget("recInfoSave", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerRecorder::recInfoDialog_save_clicked_cb));
recdir = ManglerConfig::confdir() + "/recordings";
DIR *testdir;
if ((testdir = opendir(recdir.c_str()))) {
closedir(testdir);
} else {
mkdir(recdir.c_str(), 0700);
}
filedialog->set_current_folder(recdir);
isPlaying = false;
isRecording = false;
vrfh = NULL;
player = NULL;
}/*}}}*/
ManglerRecorder::~ManglerRecorder() {/*{{{*/
reset(true);
delete filedialog;
}/*}}}*/
void
ManglerRecorder::show(void) {/*{{{*/
recWindow->present();
}/*}}}*/
void
ManglerRecorder::hide_activate_cb(void) {/*{{{*/
recWindow->hide();
}/*}}}*/
void
ManglerRecorder::open_activate_cb(void) {/*{{{*/
int result = filedialog->run();
filedialog->hide();
if (result == Gtk::RESPONSE_OK) {
path = filedialog->get_current_folder();
filename = filedialog->get_filename();
set(false);
}
}/*}}}*/
void
ManglerRecorder::close_activate_cb(void) {/*{{{*/
reset();
}/*}}}*/
void
ManglerRecorder::saveas_activate_cb(void) {/*{{{*/
}/*}}}*/
void
ManglerRecorder::delete_activate_cb(void) {/*{{{*/
if (!vrfh || filename.empty()) {
return;
}
Gtk::MessageDialog confirm("Are you sure you want to delete \"" + fileentry->get_text() + "\"?",
true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
if (confirm.run() == Gtk::RESPONSE_YES) {
reset();
unlink(filename.c_str());
}
}/*}}}*/
void
ManglerRecorder::playpause_clicked_cb(void) {/*{{{*/
if (!vrfh) {
return;
}
isPlaying = true;
player = Glib::Thread::create(sigc::mem_fun(*this, &ManglerRecorder::play), false);
}/*}}}*/
void
ManglerRecorder::stop_clicked_cb(void) {/*{{{*/
player = NULL;
}/*}}}*/
void
ManglerRecorder::record_toggled_cb(void) {/*{{{*/
if (recordbutton->get_active()) {
path = recdir;
filename = path + "/" + timestamp() + ".vrf";
set(true);
} else {
set(false);
}
}/*}}}*/
void
ManglerRecorder::info_clicked_cb(void) {/*{{{*/
if (!vrfh) {
return;
}
v3_vrf_data vrfd;
if (v3_vrf_get_info(vrfh, &vrfd) != V3_OK) {
mangler->errorDialog(c_to_ustring(_v3_error(NULL)));
return;
}
builder->get_widget("recInfoByEntry", entry);
entry->set_text(c_to_ustring(vrfd.username));
builder->get_widget("recInfoComment", textview);
textview->get_buffer()->set_text(c_to_ustring(vrfd.comment));
builder->get_widget("recInfoURL", textview);
textview->get_buffer()->set_text(c_to_ustring(vrfd.url));
builder->get_widget("recInfoCopyright", textview);
textview->get_buffer()->set_text(c_to_ustring(vrfd.copyright));
recInfoDialog->set_icon(mangler->icons["tray_icon"]);
recInfoDialog->present();
}/*}}}*/
void
ManglerRecorder::recListTree_cursor_changed_cb(void) {/*{{{*/
if (!vrfh) {
return;
}
builder->get_widget("recPlayPause", widget);
widget->set_sensitive(recListTree->get_selection()->get_selected());
}/*}}}*/
void
ManglerRecorder::recListTree_row_activated_cb(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column) {/*{{{*/
if (!vrfh) {
return;
}
isPlaying = false;
player = Glib::Thread::create(sigc::mem_fun(*this, &ManglerRecorder::play), false);
}/*}}}*/
void
ManglerRecorder::set(bool isRecording) {/*{{{*/
reset();
if (isRecording) {
if (v3_vrf_record_start(filename.c_str()) != V3_OK) {
mangler->errorDialog(c_to_ustring(_v3_error(NULL)));
recordbutton->set_active(false);
return;
}
this->isRecording = true;
} else {
this->isRecording = false;
if (!(vrfh = v3_vrf_init(filename.c_str()))) {
mangler->errorDialog(c_to_ustring(_v3_error(NULL)));
return;
}
v3_vrf_data vrfd;
if (v3_vrf_get_info(vrfh, &vrfd) != V3_OK) {
reset();
mangler->errorDialog(c_to_ustring(_v3_error(NULL)));
return;
}
builder->get_widget("recSize", label);
label->set_text(bytes_to_readable(vrfd.size));
builder->get_widget("recCount", label);
label->set_text(float_to_ustring(v3_vrf_get_count(vrfh), 0));
builder->get_widget("recPlatform", label);
label->set_text(c_to_ustring(vrfd.platform));
builder->get_widget("recVersion", label);
label->set_text(c_to_ustring(vrfd.version));
builder->get_widget("recCodec", label);
label->set_text(c_to_ustring(v3_get_codec(vrfd.codec, vrfd.codecformat)->name));
totalduration = 0;
for (uint32_t ctr = 0, cnt = v3_vrf_get_count(vrfh); ctr < cnt; ctr++) {
if (v3_vrf_get_segment(vrfh, ctr, &vrfd) != V3_OK) {
reset();
mangler->errorDialog(c_to_ustring(_v3_error(NULL)));
return;
}
Gtk::TreeModel::Row row = *(recListModel->append());
row[recRecord.id] = ctr;
row[recRecord.time_val] = vrfd.time;
row[recRecord.duration_val] = vrfd.duration;
row[recRecord.time] = msec_to_timestamp(vrfd.time);
row[recRecord.duration] = float_to_ustring(vrfd.duration / 1000.0, 2);
row[recRecord.status] = "";
row[recRecord.username] = c_to_ustring(vrfd.username);
row[recRecord.text] = "";
totalduration += vrfd.duration;
}
builder->get_widget("recDuration", label);
label->set_text(float_to_ustring(totalduration / 60000.0, 1) + " min");
builder->get_widget("recInfo", widget);
widget->set_sensitive(true);
}
fileentry->set_text(filename.substr(path.length() + 1));
builder->get_widget("recType", label);
label->set_text("VRF");
recListTree->set_sensitive(true);
builder->get_widget("recClose", widget);
widget->set_sensitive(true);
builder->get_widget("recDelete", widget);
widget->set_sensitive(true);
builder->get_widget("recInfos", widget);
widget->set_sensitive(true);
recScrolledWindow->get_vadjustment()->set_value(0);
if (recListModel->children().size()) {
recListTree->set_cursor(recListModel->get_path(recListModel->children().begin()));
builder->get_widget("recPlayPause", widget);
widget->grab_focus();
}
}/*}}}*/
void
ManglerRecorder::reset(bool destroying) {/*{{{*/
player = (Glib::Thread*)destroying;
isPlaying = false;
if (isRecording) {
v3_vrf_record_stop();
recordbutton->set_active(false);
}
isRecording = false;
if (vrfh) {
v3_vrf_destroy(vrfh);
vrfh = NULL;
}
recListModel->clear();
if (destroying) {
return;
}
for (int ctr = 0, cnt = recListTree->get_columns().size(); ctr < cnt; ctr++) {
recListTree->get_column(ctr)->queue_resize();
}
recListTree->set_sensitive(false);
fileentry->set_text("");
builder->get_widget("recType", label);
label->set_text("N/A");
builder->get_widget("recSize", label);
label->set_text("N/A");
builder->get_widget("recCount", label);
label->set_text("N/A");
builder->get_widget("recDuration", label);
label->set_text("N/A");
builder->get_widget("recPlatform", label);
label->set_text("N/A");
builder->get_widget("recVersion", label);
label->set_text("N/A");
builder->get_widget("recCodec", label);
label->set_text("N/A");
builder->get_widget("recClose", widget);
widget->set_sensitive(false);
builder->get_widget("recDelete", widget);
widget->set_sensitive(false);
builder->get_widget("recInfos", widget);
widget->set_sensitive(false);
builder->get_widget("recPlayPause", widget);
widget->set_sensitive(false);
builder->get_widget("recInfo", widget);
widget->set_sensitive(false);
builder->get_widget("recInfoByEntry", entry);
entry->set_text("");
builder->get_widget("recInfoComment", textview);
textview->get_buffer()->set_text("");
builder->get_widget("recInfoURL", textview);
textview->get_buffer()->set_text("");
builder->get_widget("recInfoCopyright", textview);
textview->get_buffer()->set_text("");
recInfoDialog->hide();
}/*}}}*/
void
ManglerRecorder::can_record(bool isConnected) {/*{{{*/
if (!isConnected && isRecording) {
set(false);
}
recordbutton->set_sensitive(isConnected);
}/*}}}*/
void
ManglerRecorder::record(Glib::ustring username, Glib::ustring text, uint32_t index, uint32_t time, bool stopped, bool flushed) {/*{{{*/
if (!isRecording) {
return;
}
Gtk::TreeModel::Children children = recListModel->children();
Gtk::TreeModel::Row row;
if (!flushed && !children[index]) {
row = *(recListModel->append());
row[recRecord.id] = index;
row[recRecord.time_val] = time;
row[recRecord.duration_val] = 0;
row[recRecord.diff_val] = 0;
row[recRecord.time] = msec_to_timestamp(time);
row[recRecord.duration] = float_to_ustring(0, 2);
row[recRecord.status] = "Rec";
row[recRecord.username] = username;
row[recRecord.text] = (text.length()) ? text : "";
builder->get_widget("recCount", label);
label->set_text(float_to_ustring(children.size(), 0));
recListTree->set_cursor(recListModel->get_path(row));
}
if (flushed) {
for (Gtk::TreeModel::iterator iter = children.begin(); iter != children.end(); iter++) {
(*iter)[recRecord.status] = "*";
}
return;
}
row = children[index];
if (stopped) {
row[recRecord.status] = "*";
} else {
row[recRecord.duration_val] = time - row[recRecord.time_val];
}
if (stopped || row[recRecord.diff_val] + 100 < row[recRecord.duration_val]) {
row[recRecord.diff_val] = time - row[recRecord.time_val];
row[recRecord.duration] = float_to_ustring(row[recRecord.duration_val] / 1000.0, 2);
}
}/*}}}*/
void
ManglerRecorder::play(void) {/*{{{*/
Glib::Thread *self = Glib::Thread::self();
Gtk::TreeModel::iterator iter = recListTree->get_selection()->get_selected();
Gtk::TreeModel::Children children = recListModel->children();
if (!vrfh || !iter || children.empty() || player != self) {
if (player == self) {
player = NULL;
}
return;
} else {
gdk_threads_enter();
builder->get_widget("recStop", widget);
widget->set_sensitive(true);
gdk_threads_leave();
}
std::map recData;
std::map::iterator recIter;
v3_vrf_data *next = NULL;
double elapsed;
struct timeval start, now, diff;
elapsed = (*iter)[recRecord.time_val];
gettimeofday(&start, NULL);
for (;;) {
if (!next && iter != children.end()) {
next = (v3_vrf_data *)malloc(sizeof(v3_vrf_data));
v3_vrf_data_init(next);
if (v3_vrf_get_segment(vrfh, (*iter)[recRecord.id], next) != V3_OK) {
free(next);
next = NULL;
iter++;
} else if (isPlaying && children.size()) {
gdk_threads_enter();
Gtk::Adjustment *vadjustment = recScrolledWindow->get_vadjustment();
float adj = vadjustment->get_upper() * ((*iter)[recRecord.id] / (float)children.size()) - vadjustment->get_page_size() / 2.0;
if (adj < 0) {
adj = 0;
} else if (adj > vadjustment->get_upper() - vadjustment->get_page_size()) {
adj = vadjustment->get_upper() - vadjustment->get_page_size();
}
vadjustment->set_value(adj);
recListTree->set_cursor(recListModel->get_path(iter));
gdk_threads_leave();
}
if (!isPlaying) {
iter = children.end();
}
}
gettimeofday(&now, NULL);
timeval_subtract(&diff, &now, &start);
gettimeofday(&start, NULL);
elapsed += diff.tv_sec * 1000.0 + diff.tv_usec / 1000.0;
if ((player != self || (iter == children.end() && !next)) && recData.empty()) {
if (next) {
v3_vrf_data_destroy(next);
free(next);
}
break;
}
if (next && next->time <= elapsed) {
recData[next->id] = new ManglerRecorderData(next);
next = NULL;
if (isPlaying) {
iter++;
}
}
double duration = 0;
for (recIter = recData.begin(); recIter != recData.end() && recData.size();) {
ManglerRecorderData *recd = recIter->second;
if (player == self && recd->next > elapsed) {
recIter++;
continue;
}
v3_vrf_data *vrfd = recd->vrfd;
if (player == self) {
v3_vrf_get_audio(vrfh, vrfd->id, vrfd);
}
switch ((player == self) ? vrfd->type : V3_VRF_DATA_NULL) {
case V3_VRF_DATA_AUDIO:
if (!recd->outputAudio) {
recd->outputAudio = new ManglerAudio(AUDIO_OUTPUT, vrfd->rate, vrfd->channels, 0, 0, false);
}
if (vrfd->length) {
recd->outputAudio->queue(vrfd->length, (uint8_t *)vrfd->data);
}
if (!recd->next) {
recd->next = vrfd->time;
gdk_threads_enter();
children[recIter->first][recRecord.status] = "Play";
builder->get_widget("recCodec", label);
label->set_text(c_to_ustring(v3_get_codec(vrfd->codec, vrfd->codecformat)->name));
gdk_threads_leave();
}
duration += (vrfd->length / (float)(vrfd->rate * sizeof(int16_t) * vrfd->channels)) * 1000.0;
if (duration < 10) {
continue;
}
recd->next += duration;
recIter++;
break;
case V3_VRF_DATA_TEXT:
gdk_threads_enter();
children[recIter->first][recRecord.text] = c_to_ustring(vrfd->text);
children[recIter->first][recRecord.status] = "*";
gdk_threads_leave();
recIter++;
break;
case V3_VRF_DATA_NULL:
default:
if (recd->outputAudio) {
recd->outputAudio->finish();
}
v3_vrf_data_destroy(vrfd);
free(vrfd);
delete recd;
gdk_threads_enter();
if (vrfh && children[recIter->first] && children[recIter->first][recRecord.status] == "Play") {
children[recIter->first][recRecord.status] = "*";
}
gdk_threads_leave();
recData.erase(recIter);
recIter = recData.begin();
break;
}
duration = 0;
}
usleep(10000);
}
if (!player || player == self) {
gdk_threads_enter();
builder->get_widget("recStop", widget);
widget->set_sensitive(false);
gdk_threads_leave();
}
}/*}}}*/
void
ManglerRecorder::recInfoDialog_cancel_clicked_cb(void) {/*{{{*/
recInfoDialog->hide();
}/*}}}*/
void
ManglerRecorder::recInfoDialog_save_clicked_cb(void) {/*{{{*/
if (vrfh) {
v3_vrf_data vrfd;
v3_vrf_data_init(&vrfd);
builder->get_widget("recInfoByEntry", entry);
strncpy(vrfd.username, ustring_to_c(entry->get_text()).c_str(), sizeof(vrfd.username));
builder->get_widget("recInfoComment", textview);
strncpy(vrfd.comment, ustring_to_c(textview->get_buffer()->get_text()).c_str(), sizeof(vrfd.comment));
builder->get_widget("recInfoURL", textview);
strncpy(vrfd.url, ustring_to_c(textview->get_buffer()->get_text()).c_str(), sizeof(vrfd.url));
builder->get_widget("recInfoCopyright", textview);
strncpy(vrfd.copyright, ustring_to_c(textview->get_buffer()->get_text()).c_str(), sizeof(vrfd.copyright));
if (v3_vrf_put_info(vrfh, &vrfd) != V3_OK) {
mangler->errorDialog(c_to_ustring(_v3_error(NULL)));
}
}
recInfoDialog->hide();
}/*}}}*/
Glib::ustring
ManglerRecorder::float_to_ustring(float val, int precision) {/*{{{*/
char tmp[128] = "";
snprintf(tmp, sizeof(tmp) - 1, "%.*f", precision, val);
return c_to_ustring(tmp);
}/*}}}*/
Glib::ustring
ManglerRecorder::bytes_to_readable(double size) {/*{{{*/
static const char *const suffixes[] = {
"bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
};
int s;
for (s = 0; size >= 1 << 10; s++) {
size /= 1 << 10;
}
return float_to_ustring(size, 1) + " " + c_to_ustring(suffixes[s]);
}/*}}}*/
Glib::ustring
ManglerRecorder::msec_to_timestamp(uint32_t milliseconds) {/*{{{*/
char timestamp[256] = "";
uint32_t seconds = milliseconds / 1000;
uint32_t minutes = seconds / 60;
uint32_t hours = minutes / 60;
snprintf(timestamp, sizeof(timestamp) - 1, "%02u:%02u:%02u", hours, minutes % 60, seconds % 60);
return c_to_ustring(timestamp);
}/*}}}*/
Glib::ustring
ManglerRecorder::timestamp(Glib::ustring format) {/*{{{*/
char timestamp[256] = "";
struct timeval tv;
time_t t;
struct tm *tm;
gettimeofday(&tv, NULL);
t = tv.tv_sec;
tm = localtime(&t);
if (!strftime(timestamp, sizeof(timestamp) - 1, format.c_str(), tm)) {
snprintf(timestamp, sizeof(timestamp) - 1, "%lu", tv.tv_sec * 1000000 + tv.tv_usec);
}
return c_to_ustring(timestamp);
}/*}}}*/
mangler-1.2.5/src/._manglerrecorder.cpp 0000644 0000765 0000062 00000000336 11602153752 015777 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerpulse.h 0000644 0000765 0000062 00000003673 11602153752 014561 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerpulse.h $
*
* Copyright 2009-2011 Eric Connell
* Copyright 2010-2011 Roman Tetelman
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLER_PULSE_H
#define _MANGLER_PULSE_H
#ifdef HAVE_PULSE
#include
#include
#include
#include
class ManglerPulse : public ManglerBackend {
pa_sample_spec pulse_samplespec;
pa_buffer_attr buffer_attr;
pa_simple *pulse_stream;
int pulse_error;
public:
virtual bool open(int type, Glib::ustring device, int rate, int channels);
virtual void close(bool drain = false);
virtual bool write(uint8_t *sample, uint32_t length, int channels);
virtual bool read(uint8_t* buf);
virtual Glib::ustring getAudioSubsystem(void);
ManglerPulse(uint32_t rate, uint8_t channels, uint32_t pcm_framesize);
virtual ~ManglerPulse();
static void getDeviceList(std::vector& inputDevices, std::vector& outputDevices);
};
#endif
#endif
mangler-1.2.5/src/._manglerpulse.h 0000644 0000765 0000062 00000000336 11602153752 014767 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerpulse.cpp 0000644 0000765 0000062 00000027610 11602153752 015111 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerpulse.cpp $
*
* Copyright 2009-2011 Eric Connell
* Copyright 2010-2011 Roman Tetelman
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#ifdef HAVE_PULSE
#include "mangleraudio.h"
#include "manglerpulse.h"
ManglerPulse::ManglerPulse(uint32_t rate, uint8_t channels, uint32_t pcm_framesize) {/*{{{*/
pulse_stream = NULL;
pulse_samplespec.format = PA_SAMPLE_S16NE;
pulse_samplespec.rate = rate;
pulse_samplespec.channels = channels;
buffer_attr.maxlength = -1;
buffer_attr.tlength = -1;
buffer_attr.prebuf = -1;
buffer_attr.minreq = -1;
buffer_attr.fragsize = pcm_framesize;
}/*}}}*/
ManglerPulse::~ManglerPulse() {/*{{{*/
close();
}/*}}}*/
bool
ManglerPulse::open(int type, Glib::ustring device, int rate, int channels) {/*{{{*/
pulse_samplespec.rate = rate;
pulse_samplespec.channels = channels;
if (!(pulse_stream = pa_simple_new(
NULL,
"Mangler",
(type >= AUDIO_OUTPUT) ? PA_STREAM_PLAYBACK : PA_STREAM_RECORD,
(device == "") ? NULL : device.c_str(),
(type >= AUDIO_OUTPUT) ? "Playback" : "Recording",
&pulse_samplespec,
NULL,
(type >= AUDIO_OUTPUT) ? NULL : &buffer_attr,
&pulse_error))) {
fprintf(stderr, "pulse: pa_simple_new() failed: %s\n", pa_strerror(pulse_error));
pulse_stream = NULL;
return false;
}
return true;
}/*}}}*/
void
ManglerPulse::close(bool drain) {/*{{{*/
if (pulse_stream) {
if (drain && pa_simple_drain(pulse_stream, &pulse_error) < 0) {
fprintf(stderr, "pulse: pa_simple_drain() failed: %s\n", pa_strerror(pulse_error));
}
pa_simple_free(pulse_stream);
pulse_stream = NULL;
}
}/*}}}*/
bool
ManglerPulse::write(uint8_t *sample, uint32_t length, int channels) {/*{{{*/
if (!pulse_stream) {
return false;
}
if (pa_simple_write(pulse_stream, sample, length, &pulse_error) < 0) {
fprintf(stderr, "pulse: pa_simple_write() failed: %s\n", pa_strerror(pulse_error));
return false;
}
return true;
}/*}}}*/
bool
ManglerPulse::read(uint8_t *buf) {/*{{{*/
if (!pulse_stream) {
return false;
}
if (pa_simple_read(pulse_stream, buf, buffer_attr.fragsize, &pulse_error) < 0) {
fprintf(stderr, "pulse: pa_simple_read() failed: %s\n", pa_strerror(pulse_error));
return false;
}
return true;
}/*}}}*/
Glib::ustring
ManglerPulse::getAudioSubsystem(void) {/*{{{*/
return Glib::ustring("pulse");
}/*}}}*/
// this is easier in C
typedef struct pa_devicelist {
uint8_t initialized;
char name[512];
uint32_t index;
char description[256];
} pa_devicelist_t;
static void pa_state_cb(pa_context *c, void *userdata);
static void pa_sinklist_cb(pa_context *c, const pa_sink_info *l, int eol, void *userdata);
static void pa_sourcelist_cb(pa_context *c, const pa_source_info *l, int eol, void *userdata);
static int pa_get_devicelist(pa_devicelist_t *input, pa_devicelist_t *output);
static int pa_get_devicelist(pa_devicelist_t *input, pa_devicelist_t *output) {
// Define our pulse audio loop and connection variables
pa_mainloop *pa_ml;
pa_mainloop_api *pa_mlapi;
pa_operation *pa_op;
pa_context *pa_ctx;
// We'll need these state variables to keep track of our requests
int state = 0;
int pa_ready = 0;
// Initialize our device lists
memset(input, 0, sizeof(pa_devicelist_t) * 16);
memset(output, 0, sizeof(pa_devicelist_t) * 16);
// Create a mainloop API and connection to the default server
pa_ml = pa_mainloop_new();
pa_mlapi = pa_mainloop_get_api(pa_ml);
pa_ctx = pa_context_new(pa_mlapi, "test");
// This function connects to the pulse server
pa_context_connect(pa_ctx, NULL, (pa_context_flags_t)0, NULL);
// This function defines a callback so the server will tell us it's state.
// Our callback will wait for the state to be ready. The callback will
// modify the variable to 1 so we know when we have a connection and it's
// ready.
// If there's an error, the callback will set pa_ready to 2
pa_context_set_state_callback(pa_ctx, pa_state_cb, &pa_ready);
// Now we'll enter into an infinite loop until we get the data we receive
// or if there's an error
for (;;) {
// We can't do anything until PA is ready, so just iterate the mainloop
// and continue
if (pa_ready == 0) {
pa_mainloop_iterate(pa_ml, 1, NULL);
continue;
}
// We couldn't get a connection to the server, so exit out
if (pa_ready == 2) {
pa_context_disconnect(pa_ctx);
pa_context_unref(pa_ctx);
pa_mainloop_free(pa_ml);
return -1;
}
// At this point, we're connected to the server and ready to make
// requests
switch (state) {
// State 0: we haven't done anything yet
case 0:
// This sends an operation to the server. pa_sinklist_info is
// our callback function and a pointer to our devicelist will
// be passed to the callback The operation ID is stored in the
// pa_op variable
pa_op = pa_context_get_sink_info_list(pa_ctx,
pa_sinklist_cb,
output
);
// Update state for next iteration through the loop
state++;
break;
case 1:
// Now we wait for our operation to complete. When it's
// complete our pa_output_devicelist is filled out, and we move
// along to the next state
if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
pa_operation_unref(pa_op);
// Now we perform another operation to get the source
// (input device) list just like before. This time we pass
// a pointer to our input structure
pa_op = pa_context_get_source_info_list(pa_ctx,
pa_sourcelist_cb,
input
);
// Update the state so we know what to do next
state++;
}
break;
case 2:
if (pa_operation_get_state(pa_op) == PA_OPERATION_DONE) {
// Now we're done, clean up and disconnect and return
pa_operation_unref(pa_op);
pa_context_disconnect(pa_ctx);
pa_context_unref(pa_ctx);
pa_mainloop_free(pa_ml);
return 0;
}
break;
default:
// We should never see this state
fprintf(stderr, "in state %d\n", state);
return -1;
}
// Iterate the main loop and go again. The second argument is whether
// or not the iteration should block until something is ready to be
// done. Set it to zero for non-blocking.
pa_mainloop_iterate(pa_ml, 1, NULL);
}
}
// This callback gets called when our context changes state. We really only
// care about when it's ready or if it has failed
static void pa_state_cb(pa_context *c, void *userdata) {
pa_context_state_t state;
int *pa_ready = (int *)userdata;
state = pa_context_get_state(c);
switch (state) {
// There are just here for reference
case PA_CONTEXT_UNCONNECTED:
case PA_CONTEXT_CONNECTING:
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
default:
break;
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
*pa_ready = 2;
break;
case PA_CONTEXT_READY:
*pa_ready = 1;
break;
}
}
// pa_mainloop will call this function when it's ready to tell us about a sink.
// Since we're not threading, there's no need for mutexes on the devicelist
// structure
static void pa_sinklist_cb(pa_context *c, const pa_sink_info *l, int eol, void *userdata) {
pa_devicelist_t *pa_devicelist = (pa_devicelist_t *)userdata;
int ctr = 0;
// If eol is set to a positive number, you're at the end of the list
if (eol > 0) {
return;
}
// We know we've allocated 16 slots to hold devices. Loop through our
// structure and find the first one that's "uninitialized." Copy the
// contents into it and we're done. If we receive more than 16 devices,
// they're going to get dropped. You could make this dynamically allocate
// space for the device list, but this is a simple example.
for (ctr = 0; ctr < 16; ctr++) {
if (! pa_devicelist[ctr].initialized) {
strncpy(pa_devicelist[ctr].name, l->name, 511);
strncpy(pa_devicelist[ctr].description, l->description, 255);
pa_devicelist[ctr].index = l->index;
pa_devicelist[ctr].initialized = 1;
break;
}
}
}
// See above. This callback is pretty much identical to the previous
static void pa_sourcelist_cb(pa_context *c, const pa_source_info *l, int eol, void *userdata) {
pa_devicelist_t *pa_devicelist = (pa_devicelist_t *)userdata;
int ctr = 0;
if (eol > 0) {
return;
}
for (ctr = 0; ctr < 16; ctr++) {
if (! pa_devicelist[ctr].initialized) {
strncpy(pa_devicelist[ctr].name, l->name, 511);
strncpy(pa_devicelist[ctr].description, l->description, 255);
pa_devicelist[ctr].index = l->index;
pa_devicelist[ctr].initialized = 1;
break;
}
}
}/*}}}*/
void
ManglerPulse::getDeviceList(std::vector& inputDevices, std::vector& outputDevices) {
int ctr;
// This is where we'll store the input device list
pa_devicelist_t pa_input_devicelist[16];
// This is where we'll store the output device list
pa_devicelist_t pa_output_devicelist[16];
if (pa_get_devicelist(pa_input_devicelist, pa_output_devicelist) < 0) {
fprintf(stderr, "pulse: failed to get device list; is pulseaudio running?\n");
return;
}
for (ctr = 0; ctr < 16; ctr++) {
if (! pa_output_devicelist[ctr].initialized) {
break;
}
outputDevices.push_back(
new ManglerAudioDevice(
pa_output_devicelist[ctr].index,
pa_output_devicelist[ctr].name,
pa_output_devicelist[ctr].description)
);
}
for (ctr = 0; ctr < 16; ctr++) {
if (! pa_input_devicelist[ctr].initialized) {
break;
}
inputDevices.push_back(
new ManglerAudioDevice(
pa_input_devicelist[ctr].index,
pa_input_devicelist[ctr].name,
pa_input_devicelist[ctr].description)
);
}
return;
}
#endif
mangler-1.2.5/src/._manglerpulse.cpp 0000644 0000765 0000062 00000000336 11602153752 015322 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerprivchat.h 0000644 0000765 0000062 00000003525 11602153752 015245 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerprivchat.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLERPRIVCHAT_H
#define _MANGLERPRIVCHAT_H
class ManglerPrivChat {
public:
ManglerPrivChat(uint16_t userid);
uint16_t remoteUserId;
Glib::RefPtr builder;
Gtk::Window *chatWindow;
Gtk::Button *sendButton;
Gtk::Button *closeButton;
Gtk::Entry *chatMessage;
Gtk::TextView *chatBox;
void chatWindow_show_cb(void);
void chatWindow_hide_cb(void);
void addMessage(Glib::ustring message);
void addChatMessage(uint16_t id, Glib::ustring message);
void remoteClosed(void);
void remoteAway(void);
void remoteBack(void);
void remoteReopened(void);
void chatWindowSendChat_clicked_cb(void);
void chatWindowCloseChat_clicked_cb(void);
void clear(void);
Glib::ustring nameFromId(uint16_t user_id);
};
#endif
mangler-1.2.5/src/._manglerprivchat.h 0000644 0000765 0000062 00000000336 11602153752 015457 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerprivchat.cpp 0000644 0000765 0000062 00000007557 11757473566 015634 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2012-05-24 20:01:26 +0200 (Thu, 24 May 2012) $
* $Revision: 1159 $
* $LastChangedBy: Haxar $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerprivchat.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#include "manglerprivchat.h"
#include "manglercharset.h"
extern const char ManglerUI[];
ManglerPrivChat::ManglerPrivChat(uint16_t userid) {
// We instantiate a new builder object here to get a completely new window (hopefully)
builder = Gtk::Builder::create_from_string(ManglerUI, "privChatWindow");
builder->get_widget("privChatWindow", chatWindow);
chatWindow->signal_hide().connect(sigc::mem_fun(this, &ManglerPrivChat::chatWindowCloseChat_clicked_cb));
chatWindow->set_title(chatWindow->get_title() + " - " + nameFromId(userid));
this->remoteUserId = userid;
builder->get_widget("privSendChat", sendButton);
sendButton->signal_clicked().connect(sigc::mem_fun(this, &ManglerPrivChat::chatWindowSendChat_clicked_cb));
builder->get_widget("privChatClose", closeButton);
closeButton->signal_clicked().connect(sigc::mem_fun(this, &ManglerPrivChat::chatWindowCloseChat_clicked_cb));
builder->get_widget("privChatBox", chatBox);
builder->get_widget("privChatMessage", chatMessage);
v3_start_privchat(remoteUserId);
chatWindow->present();
}
void ManglerPrivChat::chatWindowSendChat_clicked_cb(void) {
if (chatMessage->get_text_length()) {
v3_send_privchat_message(remoteUserId, (char *)ustring_to_c(chatMessage->get_text()).c_str());
chatMessage->set_text("");
}
}
void ManglerPrivChat::chatWindowCloseChat_clicked_cb(void) {
v3_end_privchat(remoteUserId);
chatWindow->hide();
}
void ManglerPrivChat::addMessage(Glib::ustring message) {
char timestamp[200];
time_t t;
struct tm *tmp;
struct timeval tv;
Glib::RefPtr buffer = chatBox->get_buffer();
if (Mangler::config["ChatTimestamps"].toBool()) {
gettimeofday(&tv, NULL);
t = tv.tv_sec;
tmp = localtime(&t);
if (strftime(timestamp, sizeof(timestamp), "%T", tmp) != 0) {
message = "[" + Glib::ustring(timestamp) + "] " + message;
}
}
buffer->insert(buffer->end(), message + "\n");
chatBox->scroll_to(buffer->create_mark(buffer->end()), 0.0);
}
void ManglerPrivChat::remoteClosed() {
addMessage("\n*** remote user closed connection");
sendButton->set_sensitive(false);
}
void ManglerPrivChat::remoteAway() {
addMessage("\n*** remote user is now away");
}
void ManglerPrivChat::remoteBack() {
addMessage("\n*** remote user is back");
}
void ManglerPrivChat::remoteReopened() {
addMessage("\n*** remote user has reopened chat window");
sendButton->set_sensitive(true);
}
void ManglerPrivChat::addChatMessage(uint16_t id, Glib::ustring message) {
addMessage("[" + nameFromId(id) + "]: " + message);
}
Glib::ustring ManglerPrivChat::nameFromId(uint16_t user_id) {
v3_user *u = v3_get_user(user_id);
Glib::ustring name = "";
if (u) {
name = c_to_ustring(u->name);
v3_free_user(u);
} else {
name = "unknown";
}
return name;
}
mangler-1.2.5/src/._manglerprivchat.cpp 0000644 0000765 0000062 00000000336 11757473566 016035 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/mangleross.h 0000644 0000765 0000062 00000003334 11602153752 014227 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/mangleross.h $
*
* Copyright 2009-2011 Eric Connell
* Copyright 2010-2011 Roman Tetelman
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLER_OSS_H
#define _MANGLER_OSS_H
class ManglerOSS : public ManglerBackend {
int oss_fd;
uint32_t pcm_framesize;
public:
virtual bool open(int type, Glib::ustring device, int rate, int channels);
virtual void close(bool drain = false);
virtual bool write(uint8_t *sample, uint32_t length, int channels);
virtual bool read(uint8_t* buf);
virtual Glib::ustring getAudioSubsystem(void);
ManglerOSS(uint32_t rate, uint8_t channels, uint32_t pcm_framesize);
virtual ~ManglerOSS();
static void getDeviceList(std::vector& inputDevices, std::vector& outputDevices);
};
#endif
mangler-1.2.5/src/._mangleross.h 0000644 0000765 0000062 00000000336 11602153752 014443 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/mangleross.cpp 0000644 0000765 0000062 00000013235 11602153752 014563 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/mangleross.cpp $
*
* Copyright 2009-2011 Eric Connell
* Copyright 2010-2011 Roman Tetelman
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#ifdef HAVE_OSS
#include "mangleraudio.h"
#include "mangleross.h"
ManglerOSS::ManglerOSS(uint32_t rate, uint8_t channels, uint32_t pcm_framesize) {/*{{{*/
oss_fd = -1;
this->pcm_framesize = pcm_framesize;
}/*}}}*/
ManglerOSS::~ManglerOSS() {/*{{{*/
if (oss_fd >= 0) {
close();
}
}/*}}}*/
bool
ManglerOSS::open(int type, Glib::ustring device, int rate, int channels) {/*{{{*/
if ((oss_fd = ::open((device == "") ? "/dev/dsp" : device.c_str(), (type >= AUDIO_OUTPUT) ? O_WRONLY : O_RDONLY)) < 0) {
fprintf(stderr, "oss: open() %s failed: %s\n", (device == "") ? "/dev/dsp" : device.c_str(), strerror(errno));
return false;
}
int opt;
opt = AFMT_S16_NE;
if ((::ioctl(oss_fd, SNDCTL_DSP_SETFMT, &opt) < 0) || opt != AFMT_S16_NE) {
fprintf(stderr, "oss: ioctl() SNDCTL_DSP_SETFMT failed: %s\n", strerror(errno));
close();
return false;
}
opt = channels;
if ((::ioctl(oss_fd, SNDCTL_DSP_CHANNELS, &opt) < 0) || opt != (int)channels) {
fprintf(stderr, "oss: ioctl() SNDCTL_DSP_CHANNELS failed: %s\n", strerror(errno));
close();
return false;
}
opt = rate;
if ((::ioctl(oss_fd, SNDCTL_DSP_SPEED, &opt) < 0) || opt != (int)rate) {
fprintf(stderr, "oss: ioctl() SNDCTL_DSP_SPEED failed: %s\n", strerror(errno));
close();
return false;
}
return true;
}/*}}}*/
void
ManglerOSS::close(bool drain) {/*{{{*/
if (oss_fd >= 0) {
::close(oss_fd);
oss_fd = -1;
}
}/*}}}*/
bool
ManglerOSS::write(uint8_t *sample, uint32_t length, int channels) {/*{{{*/
if (oss_fd < 0) {
return false;
}
if (::write(oss_fd, sample, length) < 0) {
fprintf(stderr, "oss: write() failed: %s\n", strerror(errno));
return false;
}
return true;
}/*}}}*/
bool
ManglerOSS::read(uint8_t *buf) {/*{{{*/
if (oss_fd < 0) {
return false;
}
if (::read(oss_fd, buf, pcm_framesize) < 0) {
fprintf(stderr, "oss: read() failed: %s\n", strerror(errno));
return false;
}
return true;
}/*}}}*/
Glib::ustring
ManglerOSS::getAudioSubsystem(void) {/*{{{*/
return Glib::ustring("oss");
}/*}}}*/
void
ManglerOSS::getDeviceList(std::vector& inputDevices, std::vector& outputDevices) {/*{{{*/
int idx_p = 0, idx_c = 0;
#if SOUND_VERSION >= 0x040000
bool ossv3 = false;
int fd, dev, version = 0;
oss_sysinfo sysinfo;
oss_audioinfo ainfo;
if ((fd = ::open("/dev/mixer", O_RDONLY)) < 0) {
fprintf(stderr, "oss: open() /dev/mixer failed: %s\n", strerror(errno));
ossv3 = true;
}
if (!ossv3 && (::ioctl(fd, OSS_GETVERSION, &version) < 0 || version < 0x040000)) {
fprintf(stderr, "oss: ioctl() failed: version too old for device enumeration\n");
::close(fd);
ossv3 = true;
}
if (!ossv3 && ::ioctl(fd, SNDCTL_SYSINFO, &sysinfo) < 0) {
fprintf(stderr, "oss: ioctl() failed: %s\n", strerror(errno));
::close(fd);
ossv3 = true;
}
if (!ossv3) {
if (!sysinfo.numaudios) {
fprintf(stderr, "oss: no sound cards found!\n");
::close(fd);
return;
}
for (dev = 0; dev < sysinfo.numaudios; dev++) {
ainfo.dev = dev;
if (::ioctl(fd, SNDCTL_AUDIOINFO, &ainfo) < 0 || !ainfo.enabled) {
continue;
}
if (ainfo.caps & PCM_CAP_OUTPUT) {
outputDevices.push_back(
new ManglerAudioDevice(
idx_p++,
ainfo.devnode,
ainfo.name)
);
}
if (ainfo.caps & PCM_CAP_INPUT) {
inputDevices.push_back(
new ManglerAudioDevice(
idx_c++,
ainfo.devnode,
ainfo.name)
);
}
}
::close(fd);
return;
}
fprintf(stderr, "oss: falling back to ossv3 device listing\n");
#endif
Glib::PatternSpec dsp("dsp*");
Glib::Dir dir("/dev");
Glib::ustring path;
for (Glib::DirIterator iter = dir.begin(); iter != dir.end(); iter++) {
if (dsp.match(*iter)) {
path = "/dev/" + *iter;
outputDevices.push_back(
new ManglerAudioDevice(
idx_p++,
path,
path)
);
inputDevices.push_back(
new ManglerAudioDevice(
idx_c++,
path,
path)
);
}
}
}/*}}}*/
#endif
mangler-1.2.5/src/._mangleross.cpp 0000644 0000765 0000062 00000000336 11602153752 014776 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerosd.h 0000644 0000765 0000062 00000003124 11602153752 014205 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerosd.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLEROSD_H
#define _MANGLEROSD_H
#include "config.h"
#ifdef HAVE_XOSD
#include
#include
#include
#include
extern "C" {
#include
}
class ManglerOsd {/*{{{*/
private:
xosd *osd;
int osd_max_lines;
std::list userList;
void createOsd(void);
public:
ManglerOsd();
void destroyOsd(void);
bool checkOsdEnabled(void);
void updateOsd(void);
void addUser(uint32_t);
void removeUser(uint32_t);
};/*}}}*/
#endif
#endif
mangler-1.2.5/src/._manglerosd.h 0000644 0000765 0000062 00000000336 11602153752 014424 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerosd.cpp 0000644 0000765 0000062 00000007735 11602153752 014554 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerosd.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#include "manglerosd.h"
#ifdef HAVE_XOSD
using namespace std;
ManglerOsd::ManglerOsd() {/*{{{*/
userList = list();
osd_max_lines = 10;
osd = NULL;
}/*}}}*/
void
ManglerOsd::createOsd(void) {/*{{{*/
if (osd) {
destroyOsd();
}
osd = xosd_create(osd_max_lines);
//xosd_set_pos(osd,XOSD_top);
//xosd_set_align(osd,XOSD_center);
xosd_set_pos(osd, (xosd_pos)(Mangler::config["OnScreenDisplayVerticalPosition"].toInt()));
xosd_set_align(osd, (xosd_align)(Mangler::config["OnScreenDisplayHorizontalAlignment"].toInt()));
if (Mangler::config["OnScreenDisplayFontSize"].toDouble() > 8.0) {
Glib::ustring fontstr = Glib::ustring::compose( "-*-*-*-*-*-*-0-%1-*-*-*-*-*-*", (int)(Mangler::config["OnScreenDisplayFontSize"].toDouble() * 10.0));
xosd_set_font(osd, fontstr.c_str());
}
if (Mangler::config["OnScreenDisplayColor"].length()) {
xosd_set_colour(osd, Mangler::config["OnScreenDisplayColor"].toCString());
}
}/*}}}*/
void
ManglerOsd::destroyOsd(void) {/*{{{*/
userList.clear();
if (osd) {
xosd_destroy(osd);
osd = NULL;
}
}/*}}}*/
bool
ManglerOsd::checkOsdEnabled(void) {/*{{{*/
if (!Mangler::config["OnScreenDisplayEnabled"].toBool()) {
if (osd) {
destroyOsd();
}
return false;
} else if (!osd) {
createOsd();
}
return true;
}/*}}}*/
void
ManglerOsd::updateOsd(void) {/*{{{*/
if (!checkOsdEnabled()) {
return;
}
if (userList.empty()) {
xosd_hide(osd);
return;
}
xosd_pos mosd_pos = (xosd_pos)(Mangler::config["OnScreenDisplayVerticalPosition"].toInt());
int i = (mosd_pos == XOSD_bottom) ? osd_max_lines - 1 : 0;
list::iterator it;
for(it=userList.begin(); it!= userList.end(); ++it) {
xosd_display(osd,i,XOSD_string,it->c_str());
i += (mosd_pos == XOSD_bottom) ? -1 : 1;
if ( i >= osd_max_lines || i < 0) {
break;
}
}
while (i >= 0 && i < osd_max_lines) {
xosd_display(osd,i,XOSD_string," ");
i += (mosd_pos == XOSD_bottom) ? -1 : 1;
}
}/*}}}*/
/*
* Adds a user to the list of users talking
*/
void
ManglerOsd::addUser(uint32_t id) {/*{{{*/
if (!checkOsdEnabled()) {
return;
}
v3_user *u;
list::iterator it;
if ((u = v3_get_user(id))) {
/* Don't 're-add' existing names */
for(it=userList.begin(); it!= userList.end(); ++it) {
if (strcmp(it->c_str(),u->name)==0) {
return;
}
}
string s(u->name);
userList.push_front(s);
updateOsd();
v3_free_user(u);
}
}/*}}}*/
/*
* Remove a user to the list of users talking
*/
void
ManglerOsd::removeUser(uint32_t id) {/*{{{*/
if (!checkOsdEnabled()) {
return;
}
v3_user *u;
if ((u = v3_get_user(id))) {
string s(u->name);
userList.remove(s);
updateOsd();
v3_free_user(u);
}
}/*}}}*/
#endif
mangler-1.2.5/src/._manglerosd.cpp 0000644 0000765 0000062 00000000336 11602153752 014757 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglernetwork.h 0000644 0000765 0000062 00000002704 11602153752 015114 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglernetwork.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLERNETWORK_H
#define _MANGLERNETWORK_H
class ManglerNetwork
{
public:
ManglerNetwork(Glib::RefPtr builder);
void connect(Glib::ustring hostname, Glib::ustring port, Glib::ustring username, Glib::ustring password, Glib::ustring phonetic);
void disconnect(void);
Gtk::Button *button;
Gtk::Label *label;
Gtk::ComboBox *combobox;
Gtk::Statusbar *statusbar;
Glib::RefPtr builder;
};
#endif
mangler-1.2.5/src/._manglernetwork.h 0000644 0000765 0000062 00000000336 11602153752 015330 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglernetwork.cpp 0000644 0000765 0000062 00000006611 11602153752 015450 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglernetwork.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#include "manglernetwork.h"
#include "channeltree.h"
#include "manglersettings.h"
#include "manglercharset.h"
ManglerNetwork::ManglerNetwork(Glib::RefPtr builder) {
this->builder = builder;
}
void
ManglerNetwork::connect(Glib::ustring hostname, Glib::ustring port, Glib::ustring username, Glib::ustring password, Glib::ustring phonetic) {/*{{{*/
Glib::ustring server = hostname + ":" + port;
gdk_threads_enter();
builder->get_widget("connectButton", button);
button->set_sensitive(false);
gdk_threads_leave();
v3_debuglevel(Mangler::config["lv3_debuglevel"].toULong());
if (! v3_login((char *)server.c_str(), (char *)ustring_to_c(username).c_str(), (char *)password.c_str(), (char *)phonetic.c_str())) {
gdk_threads_enter();
button->set_label("gtk-disconnect");
mangler->errorDialog(c_to_ustring(_v3_error(NULL)));
mangler->wantDisconnect = true;
mangler->onDisconnectHandler();
builder->get_widget("statusbar", statusbar);
statusbar->pop();
statusbar->push("Not connected.");
gdk_threads_leave();
return;
}
gdk_threads_enter();
//mangler->channelTree->expand_all();
builder->get_widget("connectButton", button);
button->set_label("gtk-disconnect");
button->set_sensitive(true);
//builder->get_widget("serverTabLabel", label);
//label->set_label(server);
builder->get_widget("serverSelectComboBox", combobox);
combobox->set_sensitive(false);
mangler->statusIcon->set(mangler->icons["tray_icon_red"]);
gdk_threads_leave();
do {
_v3_net_message *msg;
if ((msg = _v3_recv(V3_BLOCK)) == NULL) {
//printf("recv() failed: %s\n", _v3_error(NULL));
return;
}
switch (_v3_process_message(msg)) {
case V3_MALFORMED:
_v3_debug(V3_DEBUG_INFO, "received malformed packet");
break;
case V3_NOTIMPL:
_v3_debug(V3_DEBUG_INFO, "packet type not implemented");
break;
case V3_OK:
_v3_debug(V3_DEBUG_INFO, "packet processed");
/*
if (v3_queue_size() > 0) {
fprintf("stderr", "there's something to do\n");
}
*/
break;
}
} while (v3_is_loggedin());
}/*}}}*/
void
ManglerNetwork::disconnect(void) {
v3_logout();
}
mangler-1.2.5/src/._manglernetwork.cpp 0000644 0000765 0000062 00000000336 11602153752 015663 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerintegration.h 0000644 0000765 0000062 00000005747 11602153752 015760 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerintegration.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLERINTEGRATION_H
#define _MANGLERINTEGRATION_H
#include "config.h"
#ifdef HAVE_LIBMPDCLIENT
# include "mpd/client.h"
#endif
#include
#include
#ifdef HAVE_DBUS
# include
# include
# include
#endif
#include
#include
enum MusicClient
{
MusicClient_None = 0,
#ifdef HAVE_LIBMPDCLIENT
MusicClient_MPD,
#endif
#ifdef HAVE_DBUS
MusicClient_Rhythmbox,
MusicClient_Amarok,
#endif
};
class ManglerIntegration{
public:
~ManglerIntegration();
ManglerIntegration();
bool update (bool forceUpdate, const gchar *data = NULL);
bool first();
void setClient (MusicClient);
Glib::ustring format() const;
bool first_sent;
Glib::ustring artist;
Glib::ustring album;
Glib::ustring title;
int get_mode() const { return mode; };
#ifdef HAVE_DBUS
DBusGProxy * get_player() { return player; };
DBusGProxy * get_shell() { return shell; };
#endif
#ifdef HAVE_LIBMPDCLIENT
struct mpd_connection *mpd_connection;
#endif
gchar * get_current_uri_dbus();
void set_current_status (int _status) { current_status = _status; };
Glib::ustring dbus_namespace;
Glib::ustring dbus_player;
Glib::ustring dbus_player_path;
Glib::ustring dbus_shell;
Glib::ustring dbus_shell_path;
Glib::ustring dbus_uri_changed;
Glib::ustring dbus_playing_changed;
Glib::ustring dbus_get_current_song;
Glib::ustring dbus_get_song_properties;
MusicClient client;
private:
// 0 = polling, 1 = listen
int mode;
int current_status;
// DBus stuff
#ifdef HAVE_DBUS
DBusGConnection *bus;
DBusGProxy *player;
DBusGProxy *shell;
#endif
};
#ifdef HAVE_DBUS
void dbus_uri_signal_callback (DBusGProxy *, const gchar *, gpointer);
void dbus_playing_changed_callback (DBusGProxy *, gboolean, gpointer);
#endif
#endif
mangler-1.2.5/src/._manglerintegration.h 0000644 0000765 0000062 00000000336 11602153752 016162 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerintegration.cpp 0000644 0000765 0000062 00000023727 11602153752 016311 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerintegration.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
// MPRIS INTERFACE: http://wiki.xmms2.xmms.se/wiki/MPRIS
#include "manglerintegration.h"
#include "config.h"
#include
using namespace std;
bool ManglerIntegration::update(bool forceUpdate, const gchar *data)
{
switch (client) {
#ifdef HAVE_LIBMPDCLIENT
case MusicClient_MPD:
{
// Get out of idle mode
mpd_idle idle_status = mpd_run_noidle (mpd_connection);
// If there was no change of song, return false, and go back in idle mode
if (idle_status != MPD_IDLE_PLAYER && !forceUpdate) {
mpd_send_idle (mpd_connection);
return false;
}
// Retrieve the status object
struct mpd_status *status = mpd_run_status (mpd_connection);
// Playback is stopped, or unknown
mpd_state current_state = mpd_status_get_state (status);
if (current_state == MPD_STATE_STOP || current_state == MPD_STATE_UNKNOWN) {
current_status = 0;
}
if (current_state == MPD_STATE_PAUSE) {
current_status = 1;
}
if (current_state == MPD_STATE_PLAY) {
current_status = 2;
}
// Get the currrent song
int current_song_pos = mpd_status_get_song_pos (status);
if (current_song_pos == -1) {
return false;
}
struct mpd_song *current_song = mpd_run_get_queue_song_pos (mpd_connection, current_song_pos);
if (current_song == NULL) {
return false;
}
// Fill the strings
artist = mpd_song_get_tag (current_song, MPD_TAG_ARTIST, 0);
title = mpd_song_get_tag (current_song, MPD_TAG_TITLE, 0);
album= mpd_song_get_tag (current_song, MPD_TAG_ALBUM, 0);
// Free the memory for the status and song objects, and go back in idle mode
mpd_status_free (status);
mpd_song_free (current_song);
mpd_send_idle (mpd_connection);
return true;
}
break;
#endif
default:
break;
}
return false;
}
ManglerIntegration::ManglerIntegration ()
{
#ifdef HAVE_LIBMPDCLIENT
mpd_connection = NULL;
#endif
}
void ManglerIntegration::setClient (MusicClient _client)
{
client = _client;
switch (client) {
case MusicClient_None:
break;
#ifdef HAVE_LIBMPDCLIENT
case MusicClient_MPD:
{
mode = 0;
const char *hostname = "localhost";
int port = 6600;
int timeout = -1;
mpd_connection = mpd_connection_new (hostname, port, timeout);
mpd_send_idle (mpd_connection);
}
break;
#endif
#ifdef HAVE_DBUS
case MusicClient_Rhythmbox:
{
mode = 1;
dbus_namespace = "org.gnome.Rhythmbox";
dbus_player = "org.gnome.Rhythmbox.Player";
dbus_player_path = "/org/gnome/Rhythmbox/Player";
dbus_shell = "org.gnome.Rhythmbox.Shell";
dbus_shell_path = "/org/gnome/Rhythmbox/Shell";
dbus_uri_changed = "playingUriChanged";
dbus_playing_changed = "playingChanged";
dbus_get_current_song = "getPlayingUri";
dbus_get_song_properties = "getSongProperties";
bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
player = dbus_g_proxy_new_for_name (bus, dbus_namespace.c_str(), dbus_player_path.c_str(), dbus_player.c_str());
shell = dbus_g_proxy_new_for_name (bus, dbus_namespace.c_str(), dbus_shell_path.c_str(), dbus_shell.c_str());
dbus_g_proxy_add_signal (player, dbus_uri_changed.c_str(), G_TYPE_STRING, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (player, dbus_uri_changed.c_str(), G_CALLBACK (dbus_uri_signal_callback), this, NULL);
dbus_g_proxy_add_signal (player, dbus_playing_changed.c_str(), G_TYPE_BOOLEAN, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (player, dbus_playing_changed.c_str(), G_CALLBACK(dbus_playing_changed_callback), this, NULL);
dbus_playing_changed_callback(NULL, FALSE, this);
}
break;
case MusicClient_Amarok:
mode = 1;
dbus_namespace = "org.kde.amarok";
dbus_player = dbus_shell = "org.gnome.Amarok.Player";
dbus_player_path = dbus_shell_path = "/Player";
dbus_uri_changed = "TrackChange";
dbus_playing_changed = "StatusChange";
dbus_get_current_song = dbus_get_song_properties = "GetMetadata";
bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
player = dbus_g_proxy_new_for_name (bus, dbus_namespace.c_str(), dbus_player_path.c_str(), dbus_player.c_str());
shell = dbus_g_proxy_new_for_name (bus, dbus_namespace.c_str(), dbus_shell_path.c_str(), dbus_shell.c_str());
dbus_g_proxy_add_signal (player, dbus_uri_changed.c_str(), G_TYPE_STRING, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (player, dbus_uri_changed.c_str(), G_CALLBACK (dbus_uri_signal_callback), this, NULL);
dbus_g_proxy_add_signal (player, dbus_playing_changed.c_str(), G_TYPE_BOOLEAN, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (player, dbus_playing_changed.c_str(), G_CALLBACK(dbus_playing_changed_callback), this, NULL);
dbus_playing_changed_callback(NULL, FALSE, this);
break;
#endif
default:
break;
}
first_sent = false;
}
#ifdef HAVE_DBUS
gchar * ManglerIntegration::get_current_uri_dbus ()
{
DBusConnection *conn;
DBusMessage *msg, *reply;
DBusMessageIter iter;
gchar *uri;
msg = dbus_message_new_method_call (dbus_namespace.c_str(), dbus_player_path.c_str(), dbus_player.c_str(), dbus_get_current_song.c_str());
if (!msg) {
return NULL;
}
dbus_message_set_auto_start (msg, FALSE);
conn = (DBusConnection *) dbus_g_connection_get_connection (bus);
reply = dbus_connection_send_with_reply_and_block(conn, msg, 5000, NULL);
dbus_message_unref (msg);
if (!reply) {
return NULL;
}
if (dbus_message_get_type(reply) != DBUS_MESSAGE_TYPE_METHOD_RETURN) {
dbus_message_unref (reply);
return NULL;
}
dbus_message_iter_init(reply, &iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
dbus_message_unref(reply);
return NULL;
}
dbus_message_iter_get_basic(&iter, &uri);
dbus_message_unref(reply);
return uri;
}
void dbus_playing_changed_callback (DBusGProxy *proxy, gboolean playing, gpointer data)
{
ManglerIntegration *integration = (ManglerIntegration *) data;
gchar *uri;
if (!playing) {
uri = integration->get_current_uri_dbus();
if (uri && strlen(uri) != 0) {
integration->set_current_status (1);
dbus_uri_signal_callback(NULL, uri, integration);
}
} else {
integration->set_current_status (2);
}
}
void dbus_uri_signal_callback (DBusGProxy *proxy, const gchar *uri, gpointer data)
{
ManglerIntegration *integration = (ManglerIntegration *) data;
GValue *value;
GHashTable *table = NULL;
g_return_if_fail (uri != NULL);
if (!dbus_g_proxy_call(integration->get_shell(), integration->dbus_get_song_properties.c_str(), NULL, G_TYPE_STRING, uri, G_TYPE_INVALID, dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &table, G_TYPE_INVALID)) {
return;
}
value = (GValue *) g_hash_table_lookup(table, "artist");
if (value != NULL && G_VALUE_HOLDS_STRING(value)) {
integration->artist = g_value_get_string(value);
}
value = (GValue *) g_hash_table_lookup(table, "album");
if (value != NULL && G_VALUE_HOLDS_STRING(value)) {
integration->album = g_value_get_string(value);
}
value = (GValue *) g_hash_table_lookup(table, "title");
if (value != NULL && G_VALUE_HOLDS_STRING(value)) {
integration->title = g_value_get_string(value);
}
g_hash_table_destroy(table);
return;
}
#endif
Glib::ustring ManglerIntegration::format () const
{
std::ostringstream os;
int _state = (int) current_status;
Glib::ustring formatted_text ("");
if (_state == 0 || _state == 1) {
return formatted_text;
}
// os << "Stopped" << ": ";
// if (_state == 1)
// os << "Paused" << ": ";
os << artist << " - " << title;
formatted_text = os.str();
return formatted_text;
}
ManglerIntegration::~ManglerIntegration()
{
#ifdef HAVE_LIBMPDCLIENT
if (mpd_connection != NULL) {
mpd_connection_free (mpd_connection);
}
#endif
}
bool ManglerIntegration::first ()
{
if (!first_sent) {
first_sent = true;
return false;
}
return true;
}
mangler-1.2.5/src/._manglerintegration.cpp 0000644 0000765 0000062 00000000336 11602153752 016515 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerg15.h 0000644 0000765 0000062 00000016137 11602153752 014024 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerg15.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLERG15_H
#define _MANGLERG15_H
#include "config.h"
#ifdef HAVE_G15
#include
#include
#include
class ManglerG15
{
public:
ManglerG15();
void addevent(Glib::ustring text);
void update(Glib::ustring server, Glib::ustring lastXmit, Glib::ustring serverJoin, Glib::ustring chanJoin, Glib::ustring ping);
private:
int fd;
g15canvas canvas;
Glib::ustring server;
Glib::ustring lastXmit;
Glib::ustring serverJoin;
Glib::ustring chanJoin;
Glib::ustring ping;
std::vector events;
};
const char g15_blank[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xBF,0x08,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x0E,0x1F,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x1E,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x1F,0x0F,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xFE,0x1E,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x01,0xFE,0x1E,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFC,0x1E,0x0F,0xF0,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x03,0xFC,0x0E,0x07,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x03,0xFC,0x1C,0x0F,0xF8,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFC,0x0C,0x07,0xF8,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x0F,0xFC,0x0C,0x07,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x0F,0xFC,0x0C,0x07,0xFC,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x84,0x47,0xFE,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x0F,0xF8,0x8C,0x47,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x0F,0xF1,0xC0,0x47,0xFE,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF1,0xC0,0x47,0xFF,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x1F,0xF3,0xC0,0x63,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x1F,0xF3,0xC0,0xC3,0xFE,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE3,0xC0,0xE3,0xFE,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x1F,0xC7,0xE0,0xE3,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x0F,0xCF,0xE0,0xE1,0xFE,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xCF,0xE0,0xE1,0xFE,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x0F,0x9F,0xF1,0xF1,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x0F,0x3F,0xF7,0xF0,0xFC,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3F,0xFF,0xF8,0xFC,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x06,0x7F,0xFF,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x02,0xFF,0xFF,0xF8,0x78,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFC,0x70,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0xFF,0xFF,0xFC,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFE,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x3F,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFC,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
#endif
#endif
mangler-1.2.5/src/._manglerg15.h 0000644 0000765 0000062 00000000336 11602153752 014233 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerg15.cpp 0000644 0000765 0000062 00000006674 11767155076 014401 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2012-06-16 21:10:54 +0200 (Sat, 16 Jun 2012) $
* $Revision: 1176 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerg15.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#include "manglerg15.h"
#ifdef HAVE_G15
ManglerG15::ManglerG15()
{
if ((fd = new_g15_screen(G15_G15RBUF)) > 0) {
memset(&canvas, 0, sizeof(g15canvas));
memcpy(&canvas.buffer, g15_blank, G15_BUFFER_LEN);
g15r_renderString(&canvas, (unsigned char *)"Mangler", 0, G15_TEXT_LARGE, 50, G15_LCD_HEIGHT/2-5);
g15_send(fd, (char *)&canvas.buffer, G15_BUFFER_LEN);
}
}
void
ManglerG15::addevent(Glib::ustring text) {
return;
vector::iterator it;
int ctr;
if (fd <= 0) {
return;
}
if (events.size() > 5) {
events.erase(events.begin());
}
events.push_back(text);
memset(&canvas, 0, sizeof(g15canvas));
memcpy(&canvas.buffer, g15_blank, G15_BUFFER_LEN);
for (ctr = 1, it = events.begin(); it < events.end(); it++, ctr+=7) {
g15r_renderString(&canvas, (unsigned char *)((Glib::ustring)*it).c_str(), 0, G15_TEXT_SMALL, 43, ctr);
//fprintf(stderr, "%s\n", ((Glib::ustring)*it).c_str() );
}
g15_send(fd, (char *)&canvas.buffer, G15_BUFFER_LEN);
}
void
ManglerG15::update(Glib::ustring server, Glib::ustring lastXmit, Glib::ustring serverJoin, Glib::ustring chanJoin, Glib::ustring ping) {
char buf[130];
if (fd <= 0) {
return;
}
if (server != "") {
this->server = server;
}
if (lastXmit != "") {
this->lastXmit = lastXmit;
}
if (serverJoin != "") {
this->serverJoin = serverJoin;
}
if (chanJoin != "") {
this->chanJoin = chanJoin;
}
if (ping != "") {
this->ping = ping;
}
memset(&canvas, 0, sizeof(g15canvas));
memset(buf, 0, 130);
sprintf(buf, "Mangler - %-25.25s ", this->server.c_str());
g15r_renderString(&canvas, (unsigned char *)buf, 0, G15_TEXT_SMALL, 0, 0);
g15r_drawLine(&canvas, 0, 6, G15_LCD_WIDTH, 6, G15_COLOR_BLACK);
sprintf(buf, "Xmit:%-32.32s", this->lastXmit.c_str());
g15r_renderString(&canvas, (unsigned char *)buf, 0, G15_TEXT_LARGE, 6, 8);
sprintf(buf, "ChanJoin: %-32.32s", this->chanJoin.c_str());
g15r_renderString(&canvas, (unsigned char *)buf, 0, G15_TEXT_MED, 0, 18);
sprintf(buf, "SrvrJoin: %-32.32s", this->serverJoin.c_str());
g15r_renderString(&canvas, (unsigned char *)buf, 0, G15_TEXT_MED, 0, 26);
sprintf(buf, "Ping : %-32.32s", this->ping.c_str());
g15r_renderString(&canvas, (unsigned char *)buf, 0, G15_TEXT_MED, 0, 34);
g15_send(fd, (char *)&canvas.buffer, G15_BUFFER_LEN);
}
#endif
mangler-1.2.5/src/._manglerg15.cpp 0000644 0000765 0000062 00000000336 11767155076 014603 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerconfig.h 0000644 0000765 0000062 00000003474 11602153752 014675 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerconfig.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLERCONFIG_H
#define _MANGLERCONFIG_H
#include "inilib.h"
class ManglerConfig {
public:
iniFile config, servers;
//Glib::Mutex mutex;
ManglerConfig();
~ManglerConfig();
static std::string confdir();
void save();
std::vector PushToTalkXKeyCodes() const;
iniValue &operator[](const string &configVar);
bool hasUserVolume(const string &server, const string &user) const;
iniValue &UserVolume(const string &server, const string &user);
bool hasUserMuted(const string &server, const string &user) const;
iniValue &UserMuted(const string &server, const string &user);
iniValue &ChannelPassword(const string &server, uint16_t channel);
private:
static const char *DefaultConfiguration;
void ConvertOldConfig();
};
#endif
mangler-1.2.5/src/._manglerconfig.h 0000644 0000765 0000062 00000000336 11602153752 015104 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerconfig.cpp 0000644 0000765 0000062 00000026745 11602153752 015236 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerconfig.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include
#include
#include
#include
#include "mangler.h"
#include "manglerconfig.h"
#include
#include "config.h"
#include "manglerserverlist.h"
#include
#include
#include
// only needed for ConvertOldConfig
#include
// config directory, relative to $HOME
#define CONFIG_DIRECTORY ".mangler"
using namespace std;
class ManglerConfigDir {/*{{{*/
public:
static void dirInit();
static string filename(const string &name);
private:
static bool &initialized();
static string &confdir();
};/*}}}*/
bool &ManglerConfigDir::initialized() { static bool myInit( false ); return myInit; }
string &ManglerConfigDir::confdir() { static string myString; return myString; }
void ManglerConfigDir::dirInit() {/*{{{*/
string homedir = getenv("HOME");
if (! homedir.length() || homedir[homedir.length()-1] != '/') homedir += "/";
confdir() = homedir + CONFIG_DIRECTORY;
if (confdir()[confdir().length()-1] == '/') confdir().erase(confdir().length()-1, confdir().npos);
DIR *confDIR = ::opendir(confdir().c_str());
if (! confDIR) {
if (::mkdir(confdir().c_str(), 0700)) {
fprintf(stderr, "Unable to make directory '%s'\n", confdir().c_str());
fprintf(stderr, "No configuration settings can be saved.\n");
return;
}
}
confdir() += "/";
initialized() = true;
}/*}}}*/
string ManglerConfigDir::filename(const string &name) {/*{{{*/
if (! initialized()) dirInit();
return confdir() + name;
}/*}}}*/
ManglerConfig::ManglerConfig() /*{{{*/
: config( ManglerConfigDir::filename("config.ini") )
, servers( ManglerConfigDir::filename("servers.ini") ) {
// this is where we check to see if config.ini was loaded
if (! config.contains("mangler")) {
struct stat statbuf;
string oldfile = getenv("HOME");
if (oldfile[oldfile.length()-1] != '/') oldfile += "/.manglerrc";
else oldfile += ".manglerrc";
if (stat(oldfile.c_str(), &statbuf) == 0) {
ConvertOldConfig();
} else {
istringstream sin( DefaultConfiguration );
config.load(sin);
}
save();
// should have something now!!
config.reload();
servers.reload();
}
}/*}}}*/
ManglerConfig::~ManglerConfig() {/*{{{*/
save(); // might as well :)
}/*}}}*/
string ManglerConfig::confdir() {/*{{{*/
string confdir = getenv("HOME");
return confdir + "/" + CONFIG_DIRECTORY;
}/*}}}*/
void ManglerConfig::ConvertOldConfig() {/*{{{*/
string buf;
config.clear();
servers.clear();
istringstream sin( DefaultConfiguration );
config.load(sin);
map serv_names;
string oldconf = getenv("HOME");
if (! oldconf.length() || oldconf[oldconf.length() - 1] != '/') oldconf += "/";
oldconf += ".manglerrc";
ifstream fin( oldconf.c_str() );
if (! fin) {
cerr << "unable to open old .manglerrc file for reading. can't convert." << endl;
}
for (int cnt = 1;;++cnt) {
getline(fin, buf);
if (fin.eof()) break;
unsigned eq_pos = 0;
while (eq_pos < buf.length() && buf[eq_pos] != '=') ++eq_pos;
if (eq_pos == buf.length()) {
cerr << "error parsing .manglerrc: line " << cnt << endl;
continue;
}
string var = buf.substr(0, eq_pos);
string val = buf.substr(eq_pos + 1, buf.npos);
if (var.substr(0, 13) == "notification.") {
var.erase(12, 1);
var[0] = 'N';
var[12] = (char)toupper(var[12]);
} else if (var.substr(0, 7) == "window.") {
if (var.substr(7, 5) == "width" || var.substr(7, 6) == "height") {
var.erase(6, 1);
var[0] = 'W';
var[6] = (char)toupper(var[6]);
} else {
var.erase(0, 7);
var[0] = (char)toupper(var[0]);
}
} else if (var.substr(0, 11) == "serverlist.") {
int serv_id = 0;
string serv_var = "";
unsigned i = 11;
while (i < var.length() && var[i] != '.') ++i;
if (i == var.length()) {
cerr << "error parsing .manglerrc: line " << cnt << ": serverlist entry without id" << endl;
continue;
}
serv_id = atoi(var.substr(11, i - 11).c_str());
serv_var = var.substr(i+1, var.npos);
if (! serv_var.length()) {
cerr << "error parsing .manglerrc: line " << cnt << ": serverlist line looks mangled ;)" << endl;
continue;
}
if (serv_var == "name") {
serv_names[serv_id] = val;
continue;
} else if (serv_var == "accept_u2u") {
serv_var = "AcceptU2U";
} else if (serv_var == "accept_pages") {
serv_var = "AcceptPages";
} else if (serv_var == "accept_privchat") {
serv_var = "AcceptPrivateChat";
} else if (serv_var == "allow_recording") {
serv_var = "AllowRecording";
} else if (serv_var == "persistent_connection") {
serv_var = "PersistentConnection";
} else if (serv_var == "persistent_comments") {
serv_var = "PersistentComments";
} else if (serv_var == "motdhash") {
serv_var = "MotdHash";
} else if (serv_var == "defaultchannelid") {
serv_var = "DefaultChannel";
} else if (serv_var == "defaultchannel") {
continue;
} else if (serv_var.substr(0, 7) == "volume.") {
string vol_usr = serv_var.substr(7, serv_var.npos);
serv_var = "UserVolume[" + vol_usr + "]";
} else if (serv_var.substr(0, 12) == "channelpass.") {
string chan_pass = serv_var.substr(12, serv_var.npos);
serv_var = "ChannelPassword[" + chan_pass + "]";
} else {
serv_var[0] = (char)toupper(serv_var[0]);
}
string serv_name = serv_names[serv_id];
if (serv_name.length()) {
servers[serv_name][serv_var] = val;
continue;
} else {
cerr << "error parsing .manglerrc: line " << cnt << ": unknown server id" << endl;
continue;
}
} else if (var.substr(0, 13) != "qc_lastserver" && var.substr(0, 14) != "lv3_debuglevel") {
var[0] = (char)toupper(var[0]);
}
// if we get here, it's a main config option
config["mangler"][var] = val;
}
fin.close();
int lcs_id = config["mangler"]["LastConnectedServerID"].toInt();
string lcs_name = serv_names[lcs_id];
config["mangler"]["LastConnectedServerName"] = lcs_name;
config["mangler"].erase("LastConnectedServerID");
}/*}}}*/
void ManglerConfig::save() {/*{{{*/
//mutex.lock();
config.save();
servers.save();
//mutex.unlock();
}/*}}}*/
std::vector ManglerConfig::PushToTalkXKeyCodes() const {/*{{{*/
int begin = 0;
uint32_t ctr;
GdkWindow *rootwin = gdk_get_default_root_window();
vector ret;
if (! config.contains("mangler") || ! config.at("mangler").contains("PushToTalkKeyValue"))
return ret;
Glib::ustring pttString = config.at("mangler").at("PushToTalkKeyValue").toUString();
Glib::ustring keyname;
for (ctr = 0; ctr < pttString.length(); ctr++) {
if (pttString[ctr] == '+') {
keyname = pttString.substr(begin, ctr-begin);
begin = ctr+1;
if (keyname[0] == '<' && keyname[keyname.length()-1] == '>') {
keyname = keyname.substr(1, keyname.length() - 2);
}
int keycode = XKeysymToKeycode(GDK_WINDOW_XDISPLAY(rootwin), XStringToKeysym(keyname.c_str()));
ret.push_back(keycode);
}
}
keyname = pttString.substr(begin, ctr-begin);
if (keyname[0] == '<' && keyname[keyname.length()-1] == '>') {
keyname = keyname.substr(1, keyname.length() - 2);
}
int keycode = XKeysymToKeycode(GDK_WINDOW_XDISPLAY(rootwin), XStringToKeysym(keyname.c_str()));
ret.push_back(keycode);
return ret;
}/*}}}*/
iniValue &ManglerConfig::operator[](const string &configVar) {/*{{{*/
return config["mangler"][configVar];
}/*}}}*/
bool ManglerConfig::hasUserVolume(const string &server, const string &user) const {/*{{{*/
string varname = string( "UserVolume[" ) + user + string( "]" );
return servers.contains(server) && servers.at(server).contains(varname);
}/*}}}*/
iniValue &ManglerConfig::UserVolume(const string &server, const string &user) {/*{{{*/
string varname = string( "UserVolume[" ) + user + string( "]" );
return servers[server][varname];
}/*}}}*/
bool ManglerConfig::hasUserMuted(const string &server, const string &user) const {/*{{{*/
string varname = string( "UserMuted[" ) + user + string( "]" );
return servers.contains(server) && servers.at(server).contains(varname);
}/*}}}*/
iniValue &ManglerConfig::UserMuted(const string &server, const string &user) {/*{{{*/
string varname = string( "UserMuted[" ) + user + string( "]" );
return servers[server][varname];
}/*}}}*/
iniValue &ManglerConfig::ChannelPassword(const string &server, uint16_t channel) {/*{{{*/
string varname = string( "ChannelPassword[" ) + iniVariant( channel ).toString() + string( "]" );
return servers[server][varname];
}/*}}}*/
const char *ManglerConfig::DefaultConfiguration = "[mangler]\n"
"PushToTalkKeyEnabled=0\n"
"PushToTalkKeyValue=\n"
"PushToTalkMouseEnabled=0\n"
"PushToTalkMouseValue=\n"
"AudioIntegrationEnabled=0\n"
"AudioIntegrationPlayer=0\n"
"VoiceActivationEnabled=0\n"
"VoiceActivationSilenceDuration=2000\n"
"VoiceActivationSensitivity=25\n"
"InputDeviceName=\n"
"InputDeviceCustomName=\n"
"OutputDeviceName=\n"
"OutputDeviceCustomName=\n"
"NotificationDeviceName=\n"
"NotificationDeviceCustomName=\n"
"NotificationLoginLogout=1\n"
"NotificationChannelEnterLeave=1\n"
"NotificationTransmitStartStop=1\n"
"NotificationTextToSpeech=1\n"
"MouseDeviceName=\n"
#ifdef HAVE_PULSE
"AudioSubsystem=pulse\n"
#elif HAVE_ALSA
"AudioSubsystem=alsa\n"
#elif HAVE_OSS
"AudioSubsystem=oss\n"
#endif
"qc_lastserver.hostname=\n"
"qc_lastserver.port=\n"
"qc_lastserver.username=\n"
"qc_lastserver.password=\n"
"LastConnectedServerId=0\n"
"lv3_debuglevel=0\n"
"MasterVolumeLevel=79\n"
"InputGainLevel=79\n"
"WindowWidth=400\n"
"WindowHeight=525\n"
"ButtonsHidden=0\n"
"ServerInfoHidden=0\n"
"GuestFlagHidden=0\n"
"ChatTimestamps=1\n";
mangler-1.2.5/src/._manglerconfig.cpp 0000644 0000765 0000062 00000000336 11602153752 015437 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerchat.h 0000644 0000765 0000062 00000006372 11602153752 014347 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerchat.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLERCHAT_H
#define _MANGLERCHAT_H
class ManglerChat {
public:
ManglerChat(Glib::RefPtr builder);
Glib::RefPtr builder;
class chatUserModelColumns : public Gtk::TreeModel::ColumnRecord {
public:
chatUserModelColumns() { add(id); add(name); add(channel);}
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn name;
Gtk::TreeModelColumn channel;
};
chatUserModelColumns chatUserColumns;
Glib::RefPtr chatUserTreeModel;
Glib::RefPtr chatUserTreeModelFilter;
Gtk::TreeView *chatUserListView;
Gtk::TreeModel::iterator chatUserIter;
Gtk::TreeModel::Row chatUserRow;
//Glib::RefPtr chatUserSelection; // probably not needed for this
Gtk::Window *chatWindow;
Gtk::Button *button;
Gtk::Entry *chatMessage;
Gtk::CheckButton *checkbutton;
Gtk::TextView *chatBox;
std::map histEntry;
std::map::iterator histIter;
uint32_t histCount;
uint32_t histPos;
bool isOpen;
bool isJoined;
bool isPerChannel;
void chatTimestampCheckButton_toggled_cb(void);
void chatWindow_show_cb(void);
void chatWindow_hide_cb(void);
void chatMessage_activate_cb(void);
bool chatMessage_key_press_event_cb(GdkEventKey* event);
void chatClear_clicked_cb(void);
void chatClose_clicked_cb(void);
void chatHide_clicked_cb(void);
void addChatMessage(uint16_t user_id, Glib::ustring message);
void addRconMessage(Glib::ustring message);
void addMessage(Glib::ustring message);
void updateUser(uint16_t user_id);
void addUser(uint16_t user_id);
void clear(void);
void removeUser(uint16_t user_id);
bool isUserInChat(uint16_t user_id);
Glib::ustring nameFromId(uint16_t user_id);
bool filterVisible(const Gtk::TreeIter& iter);
};
#endif
mangler-1.2.5/src/._manglerchat.h 0000644 0000765 0000062 00000000336 11602153752 014556 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerchat.cpp 0000644 0000765 0000062 00000021713 11602153752 014676 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerchat.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#include "manglerchat.h"
#include "manglersettings.h"
#include "manglerconfig.h"
#include "manglercharset.h"
ManglerChat::ManglerChat(Glib::RefPtr builder) {/*{{{*/
this->builder = builder;
builder->get_widget("chatWindow", chatWindow);
chatWindow->signal_show().connect(sigc::mem_fun(this, &ManglerChat::chatWindow_show_cb));
chatWindow->signal_hide().connect(sigc::mem_fun(this, &ManglerChat::chatWindow_hide_cb));
builder->get_widget("chatMessage", chatMessage);
chatMessage->signal_activate().connect(sigc::mem_fun(this, &ManglerChat::chatMessage_activate_cb));
chatMessage->signal_key_press_event().connect(sigc::mem_fun(this, &ManglerChat::chatMessage_key_press_event_cb));
builder->get_widget("chatClear", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerChat::chatClear_clicked_cb));
builder->get_widget("chatClose", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerChat::chatClose_clicked_cb));
builder->get_widget("chatHide", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerChat::chatHide_clicked_cb));
builder->get_widget("chatUserListTreeView", chatUserListView);
chatUserTreeModel = Gtk::ListStore::create(chatUserColumns);
chatUserTreeModelFilter = Gtk::TreeModelFilter::create(chatUserTreeModel);
chatUserTreeModelFilter->set_visible_func( sigc::mem_fun(*this, &ManglerChat::filterVisible) );
chatUserListView->set_model(chatUserTreeModelFilter);
chatUserListView->append_column("Name", chatUserColumns.name);
builder->get_widget("chatTimestampCheckButton", checkbutton);
checkbutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerChat::chatTimestampCheckButton_toggled_cb));
builder->get_widget("chatBox", chatBox);
histCount = 0;
histPos = 0;
isOpen = false;
isJoined = false;
}/*}}}*/
void ManglerChat::chatTimestampCheckButton_toggled_cb(void) {/*{{{*/
builder->get_widget("chatTimestampCheckButton", checkbutton);
Mangler::config["ChatTimestamps"] = checkbutton->get_active();
Mangler::config.config.save();
}/*}}}*/
void ManglerChat::chatWindow_show_cb(void) {/*{{{*/
isOpen = true;
if (v3_is_loggedin() && !isJoined) {
v3_join_chat();
isJoined = true;
}
chatMessage->grab_focus();
builder->get_widget("chatTimestampCheckButton", checkbutton);
checkbutton->set_active(Mangler::config["ChatTimestamps"].toBool());
}/*}}}*/
void ManglerChat::chatWindow_hide_cb(void) {/*{{{*/
isOpen = false;
}/*}}}*/
void ManglerChat::chatMessage_activate_cb(void) {/*{{{*/
if (chatMessage->get_text_length()) {
histEntry[histCount] = chatMessage->get_text();
histEntry[histPos = ++histCount] = "";
v3_send_chat_message((char *)ustring_to_c(chatMessage->get_text()).c_str());
chatMessage->set_text("");
}
}/*}}}*/
bool ManglerChat::chatMessage_key_press_event_cb(GdkEventKey* event) {/*{{{*/
switch (event->keyval) {
case GDK_Up:
if ((histIter = histEntry.find(histPos - 1)) != histEntry.end()) {
if (histPos == histCount) {
histEntry[histPos] = chatMessage->get_text();
}
histPos--;
chatMessage->set_text(histIter->second);
chatMessage->set_position(histIter->second.length());
}
return true;
case GDK_Down:
if ((histIter = histEntry.find(histPos + 1)) != histEntry.end()) {
histPos++;
chatMessage->set_text(histIter->second);
chatMessage->set_position(histIter->second.length());
}
return true;
}
return false;
}/*}}}*/
void ManglerChat::chatClear_clicked_cb(void) {/*{{{*/
chatBox->get_buffer()->set_text("");
histEntry.clear();
histCount = 0;
histPos = 0;
}/*}}}*/
void ManglerChat::chatClose_clicked_cb(void) {/*{{{*/
if (v3_is_loggedin()) {
v3_leave_chat();
}
isJoined = false;
chatWindow->hide();
}/*}}}*/
void ManglerChat::chatHide_clicked_cb(void) {/*{{{*/
chatWindow->hide();
}/*}}}*/
void ManglerChat::addMessage(Glib::ustring message) {/*{{{*/
char timestamp[200];
time_t t;
struct tm *tmp;
struct timeval tv;
Glib::RefPtr buffer = chatBox->get_buffer();
if (Mangler::config["ChatTimestamps"].toBool()) {
gettimeofday(&tv, NULL);
t = tv.tv_sec;
tmp = localtime(&t);
if (strftime(timestamp, sizeof(timestamp), "%T", tmp) != 0) {
message = "[" + Glib::ustring(timestamp) + "] " + message;
}
}
buffer->insert(buffer->end(), message + "\n");
chatBox->scroll_to(buffer->create_mark(buffer->end()), 0.0);
}/*}}}*/
Glib::ustring ManglerChat::nameFromId(uint16_t user_id) {/*{{{*/
Gtk::TreeModel::Children::iterator iter = chatUserTreeModel->children().begin();
while (iter != chatUserTreeModel->children().end()) {
if (iter && (*iter)[chatUserColumns.id] == user_id) {
return (*iter)[chatUserColumns.name];
}
iter++;
}
return "";
}/*}}}*/
void ManglerChat::addChatMessage(uint16_t user_id, Glib::ustring message) {/*{{{*/
addMessage("[" + nameFromId(user_id) + "]: " + message);
}/*}}}*/
void ManglerChat::addRconMessage(Glib::ustring message) {/*{{{*/
addMessage("* [RCON]: " + message);
}/*}}}*/
void ManglerChat::addUser(uint16_t user_id) {/*{{{*/
if (isUserInChat(user_id)) {
return;
}
v3_user *u;
Glib::ustring name;
if ((u = v3_get_user(user_id))) {
name = c_to_ustring(u->name);
v3_free_user(u);
} else {
return;
}
chatUserIter = chatUserTreeModel->append();
chatUserRow = *chatUserIter;
chatUserRow[chatUserColumns.id] = user_id;
chatUserRow[chatUserColumns.name] = name;
chatUserRow[chatUserColumns.channel] = v3_get_user_channel(user_id);
chatUserTreeModelFilter->refilter();
if (!isPerChannel || (v3_get_user_channel(user_id) == v3_get_user_channel(v3_get_user_id())) ) {
addMessage("* " + name + " has joined the chat.");
}
}/*}}}*/
void ManglerChat::removeUser(uint16_t user_id) {/*{{{*/
Gtk::TreeModel::Row row;
Gtk::TreeModel::Children::iterator iter = chatUserTreeModel->children().begin();
while (iter != chatUserTreeModel->children().end()) {
row = *iter;
uint32_t rowId = row[chatUserColumns.id];
if (rowId == user_id) {
if (!isPerChannel || (v3_get_user_channel(user_id) == v3_get_user_channel(v3_get_user_id())) ) {
addMessage("* " + row[chatUserColumns.name] + " has left the chat.");
}
chatUserTreeModel->erase(row);
chatUserTreeModelFilter->refilter();
return;
}
iter++;
}
return;
}/*}}}*/
bool ManglerChat::filterVisible(const Gtk::TreeIter& iter) {/*{{{*/
uint16_t theirChannel = (*iter)[chatUserColumns.channel];
if (((*iter)[chatUserColumns.id] == v3_get_user_id()) || !isPerChannel || (theirChannel == v3_get_user_channel(v3_get_user_id()))) {
return true;
}
return false;
}/*}}}*/
void ManglerChat::clear(void) {/*{{{*/
chatUserTreeModel->clear();
addMessage("*** disconnected from server");
isJoined = false;
}/*}}}*/
bool ManglerChat::isUserInChat(uint16_t user_id) {/*{{{*/
Gtk::TreeModel::Row row;
Gtk::TreeModel::Children::iterator iter = chatUserTreeModel->children().begin();
while (iter != chatUserTreeModel->children().end()) {
row = *iter;
uint32_t rowId = row[chatUserColumns.id];
if (rowId == user_id) {
return true;
}
iter++;
}
return false;
}/*}}}*/
void ManglerChat::updateUser(uint16_t user_id) {/*{{{*/
Gtk::TreeModel::Children::iterator iter = chatUserTreeModel->children().begin();
while (iter != chatUserTreeModel->children().end()) {
if ((*iter)[chatUserColumns.id] == user_id) {
(*iter)[chatUserColumns.channel] = v3_get_user_channel(user_id);
return;
}
iter++;
}
return;
}/*}}}*/
mangler-1.2.5/src/._manglerchat.cpp 0000644 0000765 0000062 00000000336 11602153752 015111 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglercharset.h 0000644 0000765 0000062 00000002274 11602153752 015056 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglercharset.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLERCHARSET_H
#define _MANGLERCHARSET_H
extern const char *charsetslist[];
void set_charset(Glib::ustring charset);
Glib::ustring c_to_ustring(const char *input);
std::string ustring_to_c(Glib::ustring input);
#endif
mangler-1.2.5/src/._manglercharset.h 0000644 0000765 0000062 00000000336 11602153752 015270 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglercharset.cpp 0000644 0000765 0000062 00000012133 11602153752 015404 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglercharset.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#include "manglercharset.h"
Glib::ustring serverCharset;
const char *charsetslist[] = {
"System default",
"ISO-8859-15 (Western Europe)",
"ISO-8859-2 (Central Europe)",
"ISO-8859-5 (Ukrainian)",
"ISO-8859-7 (Greek)",
"ISO-8859-8 (Hebrew)",
"ISO-8859-9 (Turkish)",
"ISO-2022-JP (Japanese)",
"SJIS (Japanese)",
"CP949 (Korean)",
"CP1251 (Cyrillic)",
"KOI8-R (Cyrillic)",
"CP1256 (Arabic)",
"CP1257 (Baltic)",
"GB18030 (Chinese)",
"TIS-620 (Thai)",
NULL
};
static Glib::ustring iso_8859_1_to_utf8 (const char *input) {/*{{{*/
Glib::ustring output;
unsigned char *text = (unsigned char *)input;
int len = strlen(input);
static const gunichar lowtable[] = /* 74 byte table for 80-a4 */
{
/* compressed utf-8 table */
0x20ac, /* 80 Euro. CP1252 from here on... */
0x81, /* 81 NA */
0x201a, /* 82 */
0x192, /* 83 */
0x201e, /* 84 */
0x2026, /* 85 */
0x2020, /* 86 */
0x2021, /* 87 */
0x2c6, /* 88 */
0x2030, /* 89 */
0x160, /* 8a */
0x2039, /* 8b */
0x152, /* 8c */
0x8d, /* 8d NA */
0x17d, /* 8e */
0x8f, /* 8f NA */
0x90, /* 90 NA */
0x2018, /* 91 */
0x2019, /* 92 */
0x201c, /* 93 */
0x201d, /* 94 */
0x2022, /* 95 */
0x2013, /* 96 */
0x2014, /* 97 */
0x2dc, /* 98 */
0x2122, /* 99 */
0x161, /* 9a */
0x203a, /* 9b */
0x153, /* 9c */
0x9d, /* 9d NA */
0x17e, /* 9e */
0x178, /* 9f */
0xa0, /* a0 */
0xa1, /* a1 */
0xa2, /* a2 */
0xa3, /* a3 */
0x20ac /* a4 ISO-8859-15 Euro. */
};
while (len) {
if (G_UNLIKELY(*text >= 0x80) && G_UNLIKELY(*text <= 0xa4)) {
int idx = *text - 0x80;
output += lowtable[idx];
} else {
output += (gunichar)*text; /* ascii/iso88591 maps directly */
}
text++;
len--;
}
return output;
}/*}}}*/
void set_charset(Glib::ustring charset) {/*{{{*/
charset = charset.uppercase();
if (charset.find(' ') != Glib::ustring::npos)
charset = charset.erase(charset.find(' '));
if (charset.empty() || !charset.compare("SYSTEM")) {
charset.clear();
} else {
try {
Glib::IConv test("UTF-8", charset);
} catch (...) {
fprintf(stderr, "Charset '%s' isn't supported by your system - using system locale\n", charset.c_str());
charset.clear();
}
}
serverCharset = charset;
}/*}}}*/
std::string ustring_to_c(Glib::ustring input) {/*{{{*/
std::string to_charset, converted;
// check if input is already 7-bit
if (input.is_ascii())
return input;
// try encoding using the selected charset, unless its some utf-8
if (!serverCharset.empty() && serverCharset.find("UTF-8") == Glib::ustring::npos) {
try {
return Glib::convert(input, serverCharset, "UTF-8");
} catch (...) {}
}
// try encoding using the locale charset, unless its some utf-8
if (Glib::get_charset(to_charset) == true)
to_charset = "ISO-8859-1";
try {
converted = Glib::convert_with_fallback(input, to_charset, "UTF-8", "?");
} catch (...) {
converted = input;
}
return converted;
}/*}}}*/
Glib::ustring c_to_ustring(const char *input) {/*{{{*/
Glib::ustring converted, input_u;
// if input is NULL, return an empty string
if (! input) return "";
input_u = input;
// check if input is already valid UTF-8
if (input_u.validate())
return input_u;
// try to convert using the chosen charset
if (!serverCharset.empty()) {
try {
return Glib::convert(input, "UTF-8", serverCharset);
} catch (...) {}
}
// try to convert using the current locale
try {
converted = Glib::locale_to_utf8(input);
} catch (...) {
// locale conversion failed
converted = iso_8859_1_to_utf8(input);
}
return converted;
}/*}}}*/
mangler-1.2.5/src/._manglercharset.cpp 0000644 0000765 0000062 00000000336 11602153752 015623 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerbackend.h 0000644 0000765 0000062 00000003471 11602153752 015014 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerbackend.h $
*
* Copyright 2009-2011 Eric Connell
* Copyright 2010-2011 Roman Tetelman
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLER_BACKEND_H
#define _MANGLER_BACKEND_H
// circular dependencies in C(++) are fun!
class ManglerAudioDevice;
class ManglerBackend {
public:
virtual bool open(int type, Glib::ustring device, int rate, int channels) = 0;
virtual void close(bool drain = false) = 0;
virtual bool write(uint8_t* sample, uint32_t length, int channels) = 0;
virtual bool read(uint8_t* buf) = 0;
virtual Glib::ustring getAudioSubsystem(void) = 0;
static ManglerBackend* getBackend(Glib::ustring audioSubsystem, uint32_t rate, uint8_t channels, uint32_t pcm_framesize);
virtual ~ManglerBackend();
static void getDeviceList(Glib::ustring audioSubsystem, std::vector& input, std::vector& output);
};
#endif
mangler-1.2.5/src/._manglerbackend.h 0000644 0000765 0000062 00000000336 11602153752 015226 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/manglerbackend.cpp 0000644 0000765 0000062 00000004613 11602153752 015346 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/manglerbackend.cpp $
*
* Copyright 2009-2011 Eric Connell
* Copyright 2010-2011 Roman Tetelman
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#include "mangleraudio.h"
#include "manglerbackend.h"
#include "manglerpulse.h"
#include "mangleralsa.h"
#include "mangleross.h"
ManglerBackend*
ManglerBackend::getBackend(Glib::ustring audioSubsystem, uint32_t rate, uint8_t channels, uint32_t pcm_framesize) {
#ifdef HAVE_PULSE
if (audioSubsystem == "pulse") {
return new ManglerPulse(rate, channels, pcm_framesize);
}
#endif
#ifdef HAVE_ALSA
if (audioSubsystem == "alsa") {
return new ManglerAlsa(rate, channels, pcm_framesize);
}
#endif
#ifdef HAVE_OSS
if (audioSubsystem == "oss") {
return new ManglerOSS(rate, channels, pcm_framesize);
}
#endif
if (audioSubsystem == "openal") {
fprintf(stderr, "no mac users\n");
return NULL;
}
fprintf(stderr, "unrecognized audio subsystem \"%s\"\n", audioSubsystem.c_str());
return NULL;
}
void
ManglerBackend::getDeviceList(Glib::ustring audioSubsystem, std::vector& input, std::vector& output) {
#ifdef HAVE_PULSE
if (audioSubsystem == "pulse") {
ManglerPulse::getDeviceList(input, output);
}
#endif
#ifdef HAVE_ALSA
if (audioSubsystem == "alsa") {
ManglerAlsa::getDeviceList(input, output);
}
#endif
#ifdef HAVE_OSS
if (audioSubsystem == "oss") {
ManglerOSS::getDeviceList(input, output);
}
#endif
}
ManglerBackend::~ManglerBackend() {
}
mangler-1.2.5/src/._manglerbackend.cpp 0000644 0000765 0000062 00000000336 11602153752 015561 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/mangleraudio.h 0000644 0000765 0000062 00000007075 11602153752 014532 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/mangleraudio.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLERAUDIO_H
#define _MANGLERAUDIO_H
#include "config.h"
#ifdef HAVE_OSS
# include
# include
# include
#endif
#ifdef HAVE_ESPEAK
# include
#endif
#include "manglerbackend.h"
#include
#include
#include
#define AUDIO_CONTROL 0
#define AUDIO_INPUT 1
#define AUDIO_OUTPUT 2
#define AUDIO_NOTIFY 3
class ManglerPCM
{
public:
ManglerPCM(uint32_t length, uint8_t *sample) {
this->length = length;
this->sample = (uint8_t *)malloc(length); // I'm a C programmer... sue me
memcpy(this->sample, sample, length);
}
~ManglerPCM() {
free(this->sample);
}
uint32_t length;
uint8_t *sample;
};
class ManglerAudioDevice
{
public:
ManglerAudioDevice(uint32_t id, Glib::ustring name, Glib::ustring description) {
this->id = id;
this->name = name;
this->description = description;
}
~ManglerAudioDevice() {
}
uint32_t id;
Glib::ustring name;
Glib::ustring description;
};
class ManglerAudio
{
public:
ManglerAudio(int type, uint32_t rate = 0, uint8_t channels = 1, uint32_t pcm_framesize = 0, uint8_t buffer = 4, bool check_loggedin = true);
~ManglerAudio();
ManglerBackend *backend;
int type;
uint32_t rate;
uint32_t pcm_framesize;
uint8_t channels;
uint8_t buffer;
bool check_loggedin;
GAsyncQueue* pcm_queue;
bool outputStreamOpen;
bool inputStreamOpen;
bool stop_output;
bool stop_input;
std::map sounds;
std::vector outputDevices;
std::vector inputDevices;
bool switchBackend(Glib::ustring audioSubsystem);
bool open(void);
void close(bool drain = false);
void queue(uint32_t length, uint8_t *sample);
void finish(bool drop = false);
void output(void);
void input(void);
void getDeviceList(Glib::ustring audioSubsystem);
void playNotification(Glib::ustring name);
void playText(Glib::ustring text);
};
int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y);
#endif
mangler-1.2.5/src/._mangleraudio.h 0000644 0000765 0000062 00000000336 11602153752 014740 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/mangleraudio.cpp 0000644 0000765 0000062 00000036712 11602153752 015065 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/mangleraudio.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#include "mangleraudio.h"
#include "mangler-sounds.h"
#include
#include "channeltree.h"
#include "manglersettings.h"
ManglerAudio::ManglerAudio(int type, uint32_t rate, uint8_t channels, uint32_t pcm_framesize, uint8_t buffer, bool check_loggedin) {/*{{{*/
this->type = type;
this->rate = rate;
this->channels = channels;
this->pcm_framesize = pcm_framesize;
this->buffer = buffer;
this->check_loggedin = check_loggedin;
outputStreamOpen = false;
inputStreamOpen = false;
backend = NULL;
if (type < AUDIO_INPUT || !rate) {
return;
}
if (type >= AUDIO_OUTPUT) {
if (!open()) {
return;
}
outputStreamOpen = true;
stop_output = false;
pcm_queue = g_async_queue_new();
Glib::Thread::create(sigc::mem_fun(*this, &ManglerAudio::output), false);
} else {
if (!pcm_framesize) {
fprintf(stderr, "pcm frame size not specified on input stream open; unsupported codec?\n");
return;
}
if (!open()) {
return;
}
inputStreamOpen = true;
stop_input = false;
Glib::Thread::create(sigc::mem_fun(*this, &ManglerAudio::input), false);
}
}/*}}}*/
ManglerAudio::~ManglerAudio() {/*{{{*/
if (backend) {
delete backend;
}
}/*}}}*/
bool
ManglerAudio::switchBackend(Glib::ustring audioSubsystem) {/*{{{*/
ManglerBackend *backend;
if (!(backend = ManglerBackend::getBackend(audioSubsystem, rate, channels, pcm_framesize))) {
return false;
}
if (this->backend) {
delete this->backend;
}
this->backend = backend;
return true;
}/*}}}*/
bool
ManglerAudio::open(void) {/*{{{*/
Glib::ustring direction;
switch (type) {
case AUDIO_INPUT:
direction = "Input";
break;
default:
case AUDIO_OUTPUT:
direction = "Output";
break;
case AUDIO_NOTIFY:
direction = "Notification";
break;
}
Glib::ustring device = Mangler::config[direction + "DeviceName"].toUString();
if (device == "Default") {
device = "";
} else if (device == "Custom") {
device = Mangler::config[direction + "DeviceCustomName"].toUString();
}
close();
if (!backend && !switchBackend(Mangler::config["AudioSubsystem"].toUString())) {
return false;
}
if (!backend->open(type, device, rate, channels)) {
return false;
}
return true;
}/*}}}*/
void
ManglerAudio::close(bool drain) {/*{{{*/
if (backend) {
backend->close(drain);
}
}/*}}}*/
void
ManglerAudio::queue(uint32_t length, uint8_t *sample) {/*{{{*/
if (!outputStreamOpen) {
return;
}
g_async_queue_push(pcm_queue, new ManglerPCM(length, sample));
}/*}}}*/
void
ManglerAudio::finish(bool drop) {/*{{{*/
if (outputStreamOpen) {
stop_output = drop;
g_async_queue_push(pcm_queue, new ManglerPCM(0, NULL));
}
if (inputStreamOpen) {
stop_input = true;
}
}/*}}}*/
void
ManglerAudio::output(void) {/*{{{*/
ManglerPCM *queuedpcm = NULL;
if (!pcm_queue) {
return;
}
g_async_queue_ref(pcm_queue);
for (;;) {
if (stop_output || (check_loggedin && !v3_is_loggedin())) {
close();
break;
}
if (buffer) {
buffer--;
ManglerPCM *bufferpcm = (ManglerPCM *)g_async_queue_pop(pcm_queue);
if (bufferpcm && bufferpcm->length) {
uint32_t prelen = (queuedpcm) ? queuedpcm->length : 0;
uint32_t buflen = prelen + bufferpcm->length;
uint8_t *bufpcm = (uint8_t *)malloc(buflen);
memcpy(bufpcm + prelen, bufferpcm->sample, bufferpcm->length);
if (queuedpcm) {
memcpy(bufpcm, queuedpcm->sample, queuedpcm->length);
delete queuedpcm;
}
delete bufferpcm;
queuedpcm = new ManglerPCM(buflen, bufpcm);
free(bufpcm);
continue;
} else {
buffer = 0;
finish();
}
}
if (!queuedpcm) {
queuedpcm = (ManglerPCM *)g_async_queue_pop(pcm_queue);
}
// finish() queues a 0 length packet to notify us that we're done
if (!queuedpcm->length) {
close(true);
break;
}
if (mangler->muteSound) {
delete queuedpcm;
queuedpcm = NULL;
continue;
}
if (Mangler::config["AudioSubsystem"].toLower() != backend->getAudioSubsystem()) {
if (!switchBackend(Mangler::config["AudioSubsystem"].toLower()) || !open()) {
break;
}
}
if (!backend->write(queuedpcm->sample, queuedpcm->length, channels)) {
close();
break;
}
delete queuedpcm;
queuedpcm = NULL;
}
outputStreamOpen = false;
close();
while (queuedpcm || (queuedpcm = (ManglerPCM *)g_async_queue_try_pop(pcm_queue))) {
delete queuedpcm;
queuedpcm = NULL;
}
g_async_queue_unref(pcm_queue);
delete this;
return;
}/*}}}*/
void
ManglerAudio::input(void) {/*{{{*/
uint8_t *buf = NULL;
struct timeval start, vastart, now, diff;
int ctr;
bool drop, xmit = false;
float seconds = 0;
register float pcmpeak = 0;
float midpeak = 0;
float vasilencedur, vasilenceelapsed;
uint8_t vapercent;
for (;;) {
if (stop_input) {
break;
}
gettimeofday(&start, NULL);
ctr = 0;
seconds = 0;
pcmpeak = 0;
midpeak = 0;
// need to send ~0.115 seconds of audio for each packet
for (;;) {
/*
if (seconds >= 0.115) {
//fprintf(stderr, "0.115 seconds of real time has elapsed\n");
break;
}
*/
if (pcm_framesize * ctr > rate * sizeof(int16_t) * 0.115) {
//fprintf(stderr, "we have 0.115 seconds of audio in %d iterations\n", ctr);
break;
}
if ((pcm_framesize*(ctr+1)) > 16384) {
fprintf(stderr, "audio frames are greater than buffer size. dropping audio frames after %f seconds\n", seconds);
drop = true;
break;
}
drop = false;
//fprintf(stderr, "reallocating %d bytes of memory\n", pcm_framesize*(ctr+1));
buf = (uint8_t *)realloc(buf, pcm_framesize*(ctr+1));
//fprintf(stderr, "reading %d bytes of memory to %lu\n", pcm_framesize, buf+(pcm_framesize*ctr));
if (Mangler::config["AudioSubsystem"].toLower() != backend->getAudioSubsystem()) {
if (!switchBackend(Mangler::config["AudioSubsystem"].toLower()) || !open()) {
stop_input = true;
break;
}
}
if (!backend->read(buf+(pcm_framesize*ctr))) {
close();
stop_input = true;
break;
}
gettimeofday(&now, NULL);
timeval_subtract(&diff, &now, &start);
seconds = (float)diff.tv_sec + ((float)diff.tv_usec / 1000000.0);
//fprintf(stderr, "iteration after %f seconds with %d bytes\n", seconds, pcm_framesize*ctr);
for (int16_t *pcmptr = (int16_t *)(buf+(pcm_framesize*ctr)); pcmptr < (int16_t *)(buf+(pcm_framesize*(ctr+1))); pcmptr++) {
pcmpeak = abs(*pcmptr) > pcmpeak ? abs(*pcmptr) : pcmpeak;
}
if (seconds >= 0.115 / 2 && !midpeak && pcmpeak) {
midpeak = log10(((pcmpeak / 0x7fff) * 9) + 1);
midpeak = (midpeak > 1) ? 1 : midpeak;
gdk_threads_enter();
mangler->inputvumeter->set_fraction(midpeak);
gdk_threads_leave();
}
ctr++;
}
if (!stop_input) {
pcmpeak = log10(((pcmpeak / 0x7fff) * 9) + 1);
pcmpeak = (pcmpeak > 1) ? 1 : pcmpeak;
gdk_threads_enter();
if (Mangler::config["VoiceActivationEnabled"].toBool() &&
!mangler->isTransmittingKey &&
!mangler->isTransmittingMouse &&
!mangler->isTransmittingButton) {
vasilencedur = Mangler::config["VoiceActivationSilenceDuration"].toInt();
vapercent = Mangler::config["VoiceActivationSensitivity"].toUInt();
if (pcmpeak * 100 >= vapercent) {
gettimeofday(&vastart, NULL);
if (!xmit) {
xmit = true;
mangler->audioControl->playNotification("talkstart");
mangler->statusIcon->set(mangler->icons["tray_icon_green"]);
v3_start_audio(V3_AUDIO_SENDTYPE_U2CCUR);
}
mangler->channelTree->setUserIcon(v3_get_user_id(), "green", true);
} else if (xmit) {
gettimeofday(&now, NULL);
timeval_subtract(&diff, &now, &vastart);
vasilenceelapsed = (float)diff.tv_sec + ((float)diff.tv_usec / 1000000.0);
if (vasilenceelapsed * 1000 >= vasilencedur) {
xmit = false;
v3_stop_audio();
mangler->channelTree->setUserIcon(v3_get_user_id(), "orange", true);
mangler->statusIcon->set(mangler->icons["tray_icon_yellow"]);
mangler->audioControl->playNotification("talkend");
} else {
mangler->channelTree->setUserIcon(v3_get_user_id(), "yellow", true);
}
}
} else {
if (!xmit) {
xmit = true;
mangler->audioControl->playNotification("talkstart");
v3_start_audio(V3_AUDIO_SENDTYPE_U2CCUR);
}
mangler->channelTree->setUserIcon(v3_get_user_id(), "green", true);
mangler->statusIcon->set(mangler->icons["tray_icon_green"]);
}
mangler->inputvumeter->set_fraction(pcmpeak);
gdk_threads_leave();
if (!drop && xmit) {
//fprintf(stderr, "sending %d bytes of audio\n", pcm_framesize * ctr);
// TODO: hard coding user to channel for now, need to implement U2U
uint32_t ret;
if ((ret = v3_send_audio(V3_AUDIO_SENDTYPE_U2CCUR, rate, buf, pcm_framesize * ctr, false)) != rate) {
if (!(rate = ret) || !open()) {
stop_input = true;
}
}
}
}
free(buf);
buf = NULL;
}
inputStreamOpen = false;
close();
gdk_threads_enter();
if (xmit) {
xmit = false;
v3_stop_audio();
mangler->audioControl->playNotification("talkend");
}
if (v3_is_loggedin()) {
mangler->channelTree->setUserIcon(v3_get_user_id(), "red");
mangler->statusIcon->set(mangler->icons["tray_icon_red"]);
}
mangler->inputvumeter->set_fraction(0);
if (mangler->inputAudio == this) {
mangler->inputAudio = NULL;
}
gdk_threads_leave();
delete this;
return;
}/*}}}*/
void
ManglerAudio::getDeviceList(Glib::ustring audioSubsystem) {/*{{{*/
outputDevices.clear();
inputDevices.clear();
ManglerBackend::getDeviceList(audioSubsystem, inputDevices, outputDevices);
}/*}}}*/
void
ManglerAudio::playNotification(Glib::ustring name) {/*{{{*/
if (mangler->muteSound) {
return;
}
if ((name == "talkstart" || name == "talkend") && !Mangler::config["NotificationTransmitStartStop"].toBool()) {
return;
}
if ((name == "channelenter" || name == "channelleave") && !Mangler::config["NotificationChannelEnterLeave"].toBool()) {
return;
}
if ((name == "login" || name == "logout") && !Mangler::config["NotificationLoginLogout"].toBool()) {
return;
}
if (sounds.empty()) {
sounds["talkstart"] = new ManglerPCM(sizeof(sound_talkstart), sound_talkstart);
sounds["talkend"] = new ManglerPCM(sizeof(sound_talkend), sound_talkend);
sounds["channelenter"] = new ManglerPCM(sizeof(sound_channelenter), sound_channelenter);
sounds["channelleave"] = new ManglerPCM(sizeof(sound_channelleave), sound_channelleave);
sounds["login"] = new ManglerPCM(sizeof(sound_login), sound_login);
sounds["logout"] = new ManglerPCM(sizeof(sound_logout), sound_logout);
}
ManglerAudio *notify = new ManglerAudio(AUDIO_NOTIFY, 44100, 1, 0, 0, false);
notify->queue(sounds[name]->length, sounds[name]->sample);
notify->finish();
}/*}}}*/
#ifdef HAVE_ESPEAK
int
espeak_synth_cb(short *wav, int numsamples, espeak_EVENT *events) {/*{{{*/
ManglerAudio *tts = (ManglerAudio *)events->user_data;
if (!numsamples) {
if (tts) {
tts->finish();
events->user_data = NULL;
}
return 1;
}
tts->queue(numsamples * sizeof(short), (uint8_t *)wav);
return 0;
}/*}}}*/
#endif
void
ManglerAudio::playText(Glib::ustring text) {/*{{{*/
if (!text.length() || !Mangler::config["NotificationTextToSpeech"].toBool()) {
return;
}
#ifdef HAVE_ESPEAK
espeak_SetSynthCallback(espeak_synth_cb);
ManglerAudio *tts = new ManglerAudio(AUDIO_NOTIFY, mangler->espeakRate, 1, 0, 0, false);
if (espeak_Synth(text.c_str(), text.length() + 1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, tts) != EE_OK) {
tts->finish();
fprintf(stderr, "espeak: synth error\n");
return;
}
#endif
}/*}}}*/
int
timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) {/*{{{*/
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}/*}}}*/
mangler-1.2.5/src/._mangleraudio.cpp 0000644 0000765 0000062 00000000336 11602153752 015273 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/mangleralsa.h 0000644 0000765 0000062 00000003623 11602153752 014344 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/mangleralsa.h $
*
* Copyright 2009-2011 Eric Connell
* Copyright 2010-2011 Roman Tetelman
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLER_ALSA_H
#define _MANGLER_ALSA_H
#ifdef HAVE_ALSA
#include
#define ALSA_BUF 640
class ManglerAlsa : public ManglerBackend {
snd_pcm_t *alsa_stream;
snd_pcm_sframes_t alsa_frames;
int alsa_error;
uint32_t pcm_framesize;
uint8_t channels;
public:
virtual bool open(int type, Glib::ustring device, int rate, int channels);
virtual void close(bool drain = false);
virtual bool write(uint8_t *sample, uint32_t length, int channels);
virtual bool read(uint8_t* buf);
virtual Glib::ustring getAudioSubsystem(void);
ManglerAlsa(uint32_t rate, uint8_t channels, uint32_t pcm_framesize);
virtual ~ManglerAlsa();
static void getDeviceList(std::vector& inputDevices, std::vector& outputDevices);
};
#endif
#endif
mangler-1.2.5/src/._mangleralsa.h 0000644 0000765 0000062 00000000336 11602153752 014557 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/mangleralsa.cpp 0000644 0000765 0000062 00000017655 11602153752 014711 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/mangleralsa.cpp $
*
* Copyright 2009-2011 Eric Connell
* Copyright 2010-2011 Roman Tetelman
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#ifdef HAVE_ALSA
#include "mangleraudio.h"
#include "mangleralsa.h"
ManglerAlsa::ManglerAlsa(uint32_t rate, uint8_t channels, uint32_t pcm_framesize) {/*{{{*/
alsa_stream = NULL;
this->pcm_framesize = pcm_framesize;
this->channels = channels;
}/*}}}*/
ManglerAlsa::~ManglerAlsa() {/*{{{*/
close();
}/*}}}*/
bool
ManglerAlsa::open(int type, Glib::ustring device, int rate, int channels) {/*{{{*/
if ((alsa_error = snd_pcm_open(
&alsa_stream,
(device == "") ? "default" : device.c_str(),
(type >= AUDIO_OUTPUT) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE,
0)) < 0) {
fprintf(stderr, "alsa: snd_pcm_open() failed: %s\n", snd_strerror(alsa_error));
alsa_stream = NULL;
return false;
}
if ((alsa_error = snd_pcm_set_params(
alsa_stream, // pcm handle
SND_PCM_FORMAT_S16_LE, // format
SND_PCM_ACCESS_RW_INTERLEAVED, // access
channels, // channels
rate, // rate
true, // soft_resample
150000)) < 0) { // latency in usec (0.15 sec)
fprintf(stderr, "alsa: snd_pcm_set_params() failed: %s\n", snd_strerror(alsa_error));
close();
return false;
}
if ((alsa_error = snd_pcm_prepare(alsa_stream)) < 0) {
fprintf(stderr, "alsa: snd_pcm_prepare() failed: %s\n", snd_strerror(alsa_error));
close();
return false;
}
if (type == AUDIO_INPUT && (alsa_error = snd_pcm_start(alsa_stream)) < 0) {
fprintf(stderr, "alsa: snd_pcm_start() failed: %s\n", snd_strerror(alsa_error));
close();
return false;
}
return true;
}/*}}}*/
void
ManglerAlsa::close(bool drain) {/*{{{*/
if (alsa_stream) {
if (drain) {
snd_pcm_drain(alsa_stream);
}
snd_pcm_close(alsa_stream);
alsa_stream = NULL;
}
}/*}}}*/
bool
ManglerAlsa::write(uint8_t *sample, uint32_t length, int channels) {/*{{{*/
uint32_t buflen;
uint32_t pcmlen = length;
uint8_t *pcmptr = sample;
while ((buflen = pcmlen >= ALSA_BUF ? ALSA_BUF : pcmlen)) {
if ((alsa_frames = snd_pcm_writei(alsa_stream, pcmptr, buflen / (sizeof(int16_t) * channels))) < 0) {
if (alsa_frames == -EPIPE) {
snd_pcm_prepare(alsa_stream);
} else if ((alsa_error = snd_pcm_recover(alsa_stream, alsa_frames, 0)) < 0) {
fprintf(stderr, "alsa: snd_pcm_writei() failed: %s\n", snd_strerror(alsa_error));
return false;
}
}
pcmlen -= buflen;
pcmptr += buflen;
}
return true;
}/*}}}*/
bool
ManglerAlsa::read(uint8_t *buf) {/*{{{*/
if ((alsa_frames = snd_pcm_readi(alsa_stream, buf, pcm_framesize / (sizeof(int16_t) * channels))) < 0) {
if (alsa_frames == -EPIPE) {
snd_pcm_prepare(alsa_stream);
} else if ((alsa_error = snd_pcm_recover(alsa_stream, alsa_frames, 0)) < 0) {
fprintf(stderr, "alsa: snd_pcm_readi() failed: %s\n", snd_strerror(alsa_error));
return false;
}
}
return true;
}/*}}}*/
Glib::ustring
ManglerAlsa::getAudioSubsystem(void) {/*{{{*/
return Glib::ustring("alsa");
}/*}}}*/
void
ManglerAlsa::getDeviceList(std::vector& inputDevices, std::vector& outputDevices) {/*{{{*/
snd_pcm_stream_t stream[2] = { SND_PCM_STREAM_PLAYBACK, SND_PCM_STREAM_CAPTURE };
int ctr;
for (ctr = 0; ctr < 2; ctr++) { // the rest is just copypasta, with bad code from alsa
snd_ctl_t *handle;
int card, err, dev, idx_p = 0, idx_c = 0;
snd_ctl_card_info_t *info;
snd_pcm_info_t *pcminfo;
card = -1;
snd_ctl_card_info_alloca(&info);
snd_pcm_info_alloca(&pcminfo);
if (snd_card_next(&card) < 0 || card < 0) {
fputs("alsa: no sound cards found!\n", stderr);
return;
}
while (card >= 0) {
char hw[256] = "";
snprintf(hw, 255, "hw:%i", card);
if ((err = snd_ctl_open(&handle, hw, 0)) < 0) {
fprintf(stderr, "alsa: control open (%i): %s\n", card, snd_strerror(err));
if (snd_card_next(&card) < 0) {
fprintf(stderr, "alsa: snd_ctl_open: snd_card_next\n");
break;
}
continue;
}
if ((err = snd_ctl_card_info(handle, info)) < 0) {
fprintf(stderr, "alsa: control hardware info (%i): %s\n", card, snd_strerror(err));
snd_ctl_close(handle);
if (snd_card_next(&card) < 0) {
fprintf(stderr, "alsa: snd_ctl_card_info: snd_card_next\n");
break;
}
continue;
}
dev = -1;
for (;;) {
if (snd_ctl_pcm_next_device(handle, &dev) < 0) {
fprintf(stderr, "alsa: snd_ctl_pcm_next_device\n");
}
if (dev < 0) {
break;
}
snd_pcm_info_set_device(pcminfo, dev);
snd_pcm_info_set_subdevice(pcminfo, 0);
snd_pcm_info_set_stream(pcminfo, stream[ctr]);
if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
if (err != -ENOENT) {
fprintf(stderr, "alsa: control digital audio info (%i): %s\n", card, snd_strerror(err));
}
continue;
}
char name[256] = "", desc[512] = "";
snprintf(name, 255, "hw:%i,%i", card, dev);
snprintf(desc, 511, "%s: %s (%s)",
snd_ctl_card_info_get_name(info),
snd_pcm_info_get_name(pcminfo),
name
);
switch (stream[ctr]) {
case SND_PCM_STREAM_PLAYBACK:
outputDevices.push_back(
new ManglerAudioDevice(
idx_p++,
name,
desc)
);
break;
case SND_PCM_STREAM_CAPTURE:
inputDevices.push_back(
new ManglerAudioDevice(
idx_c++,
name,
desc)
);
break;
}
}
snd_ctl_close(handle);
if (snd_card_next(&card) < 0) {
fprintf(stderr, "alsa: snd_card_next\n");
break;
}
}
}
}/*}}}*/
#endif
mangler-1.2.5/src/._mangleralsa.cpp 0000644 0000765 0000062 00000000336 11602153752 015112 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/mangleradmin.h 0000644 0000765 0000062 00000035006 11602153752 014514 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/mangleradmin.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef _MANGLERADMIN_H
#define _MANGLERADMIN_H
#include
extern "C" {
#include
}
class iniFile;
class adminModelColumns : public Gtk::TreeModel::ColumnRecord {
public:
adminModelColumns() { add(id); add(name); }
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn name;
};
class adminChannelStore : public Gtk::TreeStore {
public:
static Glib::RefPtr create();
adminModelColumns c;
protected:
adminChannelStore() {
set_column_types(c);
}
virtual bool row_draggable_vfunc(const Gtk::TreeModel::Path& path) const;
virtual bool row_drop_possible_vfunc(const Gtk::TreeModel::Path& dest, const Gtk::SelectionData& selection_data) const;
virtual bool drag_data_received_vfunc(const Gtk::TreeModel::Path& dest, const Gtk::SelectionData& selection_data);
};
class ManglerAdmin {
friend class adminChannelStore;
public:
static Glib::ustring trimString(Glib::ustring s);
ManglerAdmin(Glib::RefPtr builder);
~ManglerAdmin();
bool isOpen;
void show(void);
void hide(void);
void permsUpdated(bool refresh = false);
void serverSettingsUpdated(v3_server_prop &prop);
void serverSettingsSendDone(void);
void channelUpdated(v3_channel *channel);
void channelRemoved(uint32_t chanid);
void channelRemoved(v3_channel *channel);
void channelAdded(v3_channel *channel);
void channelSort(bool manual);
void channelResort(void);
void clearChannels(void);
void accountUpdated(v3_account *account);
void accountAdded(v3_account *account);
void accountRemoved(uint32_t acctid);
void accountRemoved(v3_account *account);
void clearUsers(void);
void rankUpdated(v3_rank *rank);
void rankAdded(v3_rank *rank);
void rankRemoved(uint16_t rankid);
void rankRemoved(v3_rank *rank);
void clearRanks(void);
void banList(uint16_t id, uint16_t count, uint16_t bitmask_id, uint32_t ip_address, char *user, char *by, char *reason);
void clearBans(void);
void clear(void);
protected:
Glib::RefPtr builder;
Gtk::Window *adminWindow;
Gtk::Notebook *adminNotebook;
Gtk::Alignment *ServerTab;
Gtk::Alignment *ChannelsTab;
Gtk::Alignment *UsersTab;
Gtk::Alignment *RanksTab;
Gtk::HBox *BansTab;
Gtk::Button *UserAdd;
Gtk::Statusbar *AdminStatusbar;
guint StatusbarCount;
time_t StatusbarTime;
Glib::ustring tmpldir;
Gtk::FileChooserDialog *tmpldialog;
Gtk::FileFilter tpl_filter;
Gtk::FileFilter all_filter;
adminModelColumns adminRecord;
/* server settings editor stuff */
Glib::RefPtr SrvChatFilterModel;
Glib::RefPtr SrvChanOrderModel;
Glib::RefPtr SrvInactActionModel;
Glib::RefPtr SrvInactChannelModel;
Glib::RefPtr SrvSpamFilterChannelModel;
Glib::RefPtr SrvSpamFilterChatModel;
Glib::RefPtr SrvSpamFilterCommentModel;
Glib::RefPtr SrvSpamFilterTTSModel;
Glib::RefPtr SrvSpamFilterWaveModel;
bool SrvEditorOpen;
bool SrvIsNotUpdating;
/* channel editor stuff */
adminModelColumns ChannelEditorColumns;
Glib::RefPtr ChannelEditorTreeModel;
adminModelColumns ChannelCodecColumns;
Glib::RefPtr ChannelCodecModel;
adminModelColumns ChannelFormatColumns;
Glib::RefPtr ChannelFormatModel;
adminModelColumns ChannelProtColumns;
Glib::RefPtr ChannelProtModel;
adminModelColumns ChannelVoiceColumns;
Glib::RefPtr ChannelVoiceModel;
Gtk::TreeView *ChannelEditorTree;
Gtk::Button *ChannelUpdate;
Gtk::VBox *ChannelEditor;
Gtk::Button *ChannelRemove;
Gtk::Button *ChannelAdd;
uint32_t currentChannelID;
uint32_t currentChannelParent;
bool channelSortManual;
bool ChannelAdded;
/* user editor stuff */
class adminCheckModelColumns : public Gtk::TreeModel::ColumnRecord {
public:
adminCheckModelColumns() { add(id); add(on); add(name); }
Gtk::TreeModelColumn id;
/* Gtk::CellRendererToggle toggle; */
Gtk::TreeModelColumn on;
Gtk::TreeModelColumn name;
} adminCheckRecord;
adminModelColumns UserEditorColumns;
Glib::RefPtr UserEditorTreeModel;
Gtk::TreeView *UserEditorTree;
adminCheckModelColumns UserChanAdminColumns;
Glib::RefPtr UserChanAdminModel;
Gtk::TreeView *UserChanAdminTree;
adminCheckModelColumns UserChanAuthColumns;
Glib::RefPtr UserChanAuthModel;
Gtk::TreeView *UserChanAuthTree;
adminModelColumns UserOwnerColumns;
Glib::RefPtr UserOwnerModel;
adminModelColumns UserRankColumns;
Glib::RefPtr UserRankModel;
adminModelColumns UserDuplicateIPsColumns;
Glib::RefPtr UserDuplicateIPsModel;
adminModelColumns UserDefaultChannelColumns;
Glib::RefPtr UserDefaultChannelModel;
Gtk::ComboBox *UserTemplate;
adminModelColumns UserTemplateColumns;
Glib::RefPtr UserTemplateModel;
Gtk::Table *UserInfoSection;
Gtk::VBox *UserNetworkSection;
Gtk::VBox *UserTransmitSection;
Gtk::VBox *UserDisplaySection;
Gtk::VBox *UserAdminSection;
Gtk::Button *UserUpdate;
Gtk::VBox *UserEditor;
Gtk::Button *UserRemove;
bool UserEditorOpen;
uint32_t currentUserID;
/* rank editor stuff */
class rankModelColumns : public Gtk::TreeModel::ColumnRecord {
public:
rankModelColumns() { add(id); add(name); add(level); add(description); }
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn level;
Gtk::TreeModelColumn name;
Gtk::TreeModelColumn description;
} rankRecord;
rankModelColumns RankEditorColumns;
Glib::RefPtr RankEditorModel;
Gtk::TreeView *RankEditorTree;
Gtk::VBox *RankEditor;
bool RankEditorOpen;
uint16_t currentRankID;
/* ban editor stuff */
class banModelColumns : public Gtk::TreeModel::ColumnRecord {
public:
banModelColumns() { add(id); add(ip_val); add(netmask_id); add(ip); add(netmask); add(user); add(by); add(reason); }
Gtk::TreeModelColumn id;
Gtk::TreeModelColumn ip_val;
Gtk::TreeModelColumn netmask_id;
Gtk::TreeModelColumn ip;
Gtk::TreeModelColumn netmask;
Gtk::TreeModelColumn user;
Gtk::TreeModelColumn by;
Gtk::TreeModelColumn reason;
} banRecord;
banModelColumns BanEditorColumns;
Glib::RefPtr BanEditorModel;
Gtk::TreeView *BanEditorTree;
Glib::RefPtr BanNetmaskModel;
uint16_t BanNetmaskDefault;
Gtk::VBox *BanEditor;
uint32_t currentBanIP;
/* generic pointers and window pointer */
Gtk::Widget *widget;
Gtk::Button *button;
Gtk::Entry *entry;
Gtk::CheckButton *checkbutton;
Gtk::ComboBox *combobox;
Gtk::Label *label;
Gtk::SpinButton *spinbutton;
Gtk::ToggleButton *togglebutton;
Gtk::Arrow *arrow;
/* admin window main functions and callbacks */
void adminWindow_show_cb(void);
void adminWindow_hide_cb(void);
void CloseButton_clicked_cb(void);
void copyToEntry(const char *widgetName, Glib::ustring src);
void copyToSpinbutton(const char *widgetName, uint32_t src);
void copyToCheckbutton(const char *widgetName, bool src);
void copyToCombobox(const char *widgetName, uint32_t src, uint32_t deflt = 0);
Glib::ustring getFromEntry(const char *widgetName);
uint32_t getFromSpinbutton(const char *widgetName);
bool getFromCheckbutton(const char *widgetName);
uint32_t getFromCombobox(const char *widgetName, uint32_t deflt = 0);
void setWidgetSensitive(const char *widgetName, bool widgetSens = true);
void queue_resize(Gtk::TreeView *treeview);
void statusbarPush(Glib::ustring msg);
bool statusbarPop(void);
/* server settings functions and callbacks */
void ServerUpdate_clicked_cb(void);
/* channel editor functions and callbacks */
Glib::ustring getChannelPathString(uint32_t id, Gtk::TreeModel::Children children);
Gtk::TreeModel::Row getChannel(uint32_t id, Gtk::TreeModel::Children children, bool hasCheckbox = false);
void populateChannelEditor(const v3_channel *channel);
int channelSortFunction(const Gtk::TreeModel::iterator &left, const Gtk::TreeModel::iterator &right);
void ChannelTree_cursor_changed_cb(void);
void ChannelAdd_clicked_cb(void);
void ChannelRemove_clicked_cb(void);
void ChannelUpdate_clicked_cb(void);
void LoadCodecFormats(void);
void ChannelProtMode_changed_cb(void);
void ChannelVoiceMode_changed_cb(void);
/* user editor functions and callbacks */
Gtk::TreeModel::Row getAccount(uint32_t id, Gtk::TreeModel::Children children);
void populateUserEditor(const v3_account *account, bool isTemplate = false);
void setAdminCheckTree(Gtk::TreeModel::Children children, uint16_t *chanids, int chan_count);
void getAdminCheckTree(Gtk::TreeModel::Children children, std::vector &chanids);
void getAdminCheckTree(Gtk::TreeModel::Children children, uint16_t *&chanids, int &chan_count);
void UserTree_cursor_changed_cb(void);
void UserAdd_clicked_cb(void);
void UserRemove_clicked_cb(void);
void UserUpdate_clicked_cb(void);
void UserInfoButton_toggled_cb(void);
void UserNetworkButton_toggled_cb(void);
void UserTransmitButton_toggled_cb(void);
void UserDisplayButton_toggled_cb(void);
void UserAdminButton_toggled_cb(void);
void UserChanAdminButton_toggled_cb(void);
void UserChanAuthButton_toggled_cb(void);
/* user editor 'profile' stuff */
void loadUserTemplates(void);
void UserTemplate_changed_cb(void);
void UserTemplateLoad_clicked_cb(void);
void UserTemplateDelete_clicked_cb(void);
void UserTemplateSave_clicked_cb(void);
/* rank editor functions and callbacks */
Gtk::TreeModel::iterator getRank(uint16_t id, Gtk::TreeModel::Children children);
void RankEditorTree_cursor_changed_cb(void);
void RankAdd_clicked_cb(void);
void RankRemove_clicked_cb(void);
void RankUpdate_clicked_cb(void);
void clearRankEditor(void);
/* ban editor functions and callbacks */
void BanEditorTree_cursor_changed_cb(void);
void BanAdd_clicked_cb(void);
void BanRemove_clicked_cb(void);
void BanUpdate_clicked_cb(void);
void clearBanEditor(void);
};
#endif
mangler-1.2.5/src/._mangleradmin.h 0000644 0000765 0000062 00000000336 11602153752 014727 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/mangleradmin.cpp 0000644 0000765 0000062 00000303123 11602153752 015045 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/mangleradmin.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "mangler.h"
#include "mangleradmin.h"
#include "manglercharset.h"
#include "inilib.h"
#include
#include
#include
int natsort(const char *l, const char *r);
Glib::ustring
ManglerAdmin::trimString(Glib::ustring s) {/*{{{*/
if (s.empty()) {
return s;
}
while (s.length() && (s[0] == ' ' || s[0] == '\t')) {
s.erase(0, 1);
}
if (s.empty()) {
return s;
}
for (int i = s.length() - 1; i >= 0; --i) {
if (s[i] == '\n') {
continue;
}
if (s[i] != ' ' && s[i] != '\t') {
break;
}
s.erase(i, 1);
}
return s;
}/*}}}*/
ManglerAdmin::ManglerAdmin(Glib::RefPtr builder) {/*{{{*/
/* set up the basic window variables */
this->builder = builder;
Gtk::TreeModel::Row row;
Gtk::TreeView::Column *pColumn;
Gtk::CellRendererText *renderer;
builder->get_widget("adminWindow", adminWindow);
adminWindow->signal_show().connect(sigc::mem_fun(this, &ManglerAdmin::adminWindow_show_cb));
adminWindow->signal_hide().connect(sigc::mem_fun(this, &ManglerAdmin::adminWindow_hide_cb));
builder->get_widget("adminNotebook", adminNotebook);
builder->get_widget("CloseButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::CloseButton_clicked_cb));
builder->get_widget("ServerTab", ServerTab);
ServerTab->hide();
builder->get_widget("ChannelsTab", ChannelsTab);
builder->get_widget("UsersTab", UsersTab);
builder->get_widget("RanksTab", RanksTab);
builder->get_widget("BansTab", BansTab);
builder->get_widget("AdminStatusbar", AdminStatusbar);
AdminStatusbar->set_has_resize_grip(false);
StatusbarTime = ::time(NULL);
StatusbarCount = 0;
Glib::signal_timeout().connect_seconds(sigc::mem_fun(this, &ManglerAdmin::statusbarPop), 1);
/* set up the server settings editor stuff */
builder->get_widget("ServerChatFilter", combobox);
SrvChatFilterModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvChatFilterModel);
combobox->pack_start(adminRecord.name);
row = *(SrvChatFilterModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Global to Server";
row = *(SrvChatFilterModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Per Channel";
builder->get_widget("ServerChannelOrdering", combobox);
SrvChanOrderModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvChanOrderModel);
combobox->pack_start(adminRecord.name);
row = *(SrvChanOrderModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Sort Alphabetically";
row = *(SrvChanOrderModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Manual";
builder->get_widget("ServerAction", combobox);
SrvInactActionModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvInactActionModel);
combobox->pack_start(adminRecord.name);
row = *(SrvInactActionModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Kick User";
row = *(SrvInactActionModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Move to Channel";
builder->get_widget("ServerChannel", combobox);
SrvInactChannelModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvInactChannelModel);
combobox->pack_start(adminRecord.name);
renderer = (Gtk::CellRendererText*)(*(combobox->get_cells().begin()));
renderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE;
builder->get_widget("ServerSpamFilterChannelAction", combobox);
SrvSpamFilterChannelModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvSpamFilterChannelModel);
combobox->pack_start(adminRecord.name);
row = *(SrvSpamFilterChannelModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Do Nothing";
row = *(SrvSpamFilterChannelModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Kick User";
row = *(SrvSpamFilterChannelModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Ban User";
builder->get_widget("ServerSpamFilterChatAction", combobox);
SrvSpamFilterChatModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvSpamFilterChatModel);
combobox->pack_start(adminRecord.name);
row = *(SrvSpamFilterChatModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Do Nothing";
row = *(SrvSpamFilterChatModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Kick User";
row = *(SrvSpamFilterChatModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Ban User";
builder->get_widget("ServerSpamFilterCommentAction", combobox);
SrvSpamFilterCommentModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvSpamFilterCommentModel);
combobox->pack_start(adminRecord.name);
row = *(SrvSpamFilterCommentModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Do Nothing";
row = *(SrvSpamFilterCommentModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Kick User";
row = *(SrvSpamFilterCommentModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Ban User";
builder->get_widget("ServerSpamFilterTTSAction", combobox);
SrvSpamFilterTTSModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvSpamFilterTTSModel);
combobox->pack_start(adminRecord.name);
row = *(SrvSpamFilterTTSModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Do Nothing";
row = *(SrvSpamFilterTTSModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Kick User";
row = *(SrvSpamFilterTTSModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Ban User";
builder->get_widget("ServerSpamFilterWaveAction", combobox);
SrvSpamFilterWaveModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(SrvSpamFilterWaveModel);
combobox->pack_start(adminRecord.name);
row = *(SrvSpamFilterWaveModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Do Nothing";
row = *(SrvSpamFilterWaveModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Kick User";
row = *(SrvSpamFilterWaveModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Ban User";
builder->get_widget("ServerUpdate", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::ServerUpdate_clicked_cb));
/* set up the channel editor stuff */
builder->get_widget("ChannelEditorTree", ChannelEditorTree);
ChannelEditorTreeModel = adminChannelStore::create();
ChannelEditorTree->set_model(ChannelEditorTreeModel);
pColumn = Gtk::manage( new Gtk::TreeView::Column("Channels") );
pColumn->pack_start(adminRecord.name);
pColumn->set_expand(true);
ChannelEditorTree->append_column(*pColumn);
ChannelEditorTree->signal_cursor_changed().connect(sigc::mem_fun(this, &ManglerAdmin::ChannelTree_cursor_changed_cb));
ChannelEditorTree->enable_model_drag_source();
ChannelEditorTree->enable_model_drag_dest();
builder->get_widget("ChannelEditor", ChannelEditor);
ChannelEditor->set_sensitive(false);
builder->get_widget("ChannelAdd", ChannelAdd);
ChannelAdd->set_sensitive(false);
ChannelAdd->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::ChannelAdd_clicked_cb));
builder->get_widget("ChannelRemove", ChannelRemove);
ChannelRemove->set_sensitive(false);
ChannelRemove->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::ChannelRemove_clicked_cb));
builder->get_widget("ChannelUpdate", ChannelUpdate);
ChannelUpdate->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::ChannelUpdate_clicked_cb));
currentChannelID = 0;
currentChannelParent = 0;
builder->get_widget("ChannelProtMode", combobox);
ChannelProtModel = Gtk::TreeStore::create(ChannelProtColumns);
combobox->set_model(ChannelProtModel);
combobox->pack_start(adminRecord.name);
row = *(ChannelProtModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Open to Public";
row = *(ChannelProtModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Channel Password";
row = *(ChannelProtModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "User Authorization";
combobox->signal_changed().connect(sigc::mem_fun(this, &ManglerAdmin::ChannelProtMode_changed_cb));
builder->get_widget("ChannelVoiceMode", combobox);
ChannelVoiceModel = Gtk::TreeStore::create(ChannelVoiceColumns);
combobox->set_model(ChannelVoiceModel);
combobox->pack_start(adminRecord.name);
row = *(ChannelVoiceModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "Normal";
row = *(ChannelVoiceModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Queued";
row = *(ChannelVoiceModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Muted";
combobox->signal_changed().connect(sigc::mem_fun(this, &ManglerAdmin::ChannelVoiceMode_changed_cb));
builder->get_widget("ChannelCodec", combobox);
ChannelCodecModel = Gtk::TreeStore::create(ChannelCodecColumns);
combobox->set_model(ChannelCodecModel);
combobox->pack_start(adminRecord.name);
row = *(ChannelCodecModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "GSM";
row = *(ChannelCodecModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Codec 1";
row = *(ChannelCodecModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "Codec 2";
row = *(ChannelCodecModel->append());
row[adminRecord.id] = 3; row[adminRecord.name] = "Speex";
row = *(ChannelCodecModel->append());
row[adminRecord.id] = 4; row[adminRecord.name] = "Server Default";
combobox->signal_changed().connect(sigc::mem_fun(this, &ManglerAdmin::LoadCodecFormats));
builder->get_widget("ChannelFormat", combobox);
ChannelFormatModel = Gtk::TreeStore::create(ChannelCodecColumns);
combobox->set_model(ChannelFormatModel);
combobox->pack_start(adminRecord.name);
/* set up the user editor stuff */
UserEditorTreeModel = Gtk::TreeStore::create(UserEditorColumns);
builder->get_widget("UserEditorTree", UserEditorTree);
UserEditorTree->set_model(UserEditorTreeModel);
pColumn = Gtk::manage( new Gtk::TreeView::Column("Users") );
pColumn->pack_start(adminRecord.name);
pColumn->set_expand(true);
UserEditorTree->append_column(*pColumn);
UserEditorTree->signal_cursor_changed().connect(sigc::mem_fun(this, &ManglerAdmin::UserTree_cursor_changed_cb));
UserChanAdminModel = Gtk::TreeStore::create(UserChanAdminColumns);
builder->get_widget("UserChanAdminTree", UserChanAdminTree);
UserChanAdminTree->set_model(UserChanAdminModel);
pColumn = Gtk::manage( new Gtk::TreeView::Column("Channels") );
pColumn->pack_start(adminCheckRecord.name);
pColumn->set_expand(true);
UserChanAdminTree->append_column_editable("Select", adminCheckRecord.on);
UserChanAdminTree->append_column(*pColumn);
UserChanAuthModel = Gtk::TreeStore::create(UserChanAuthColumns);
builder->get_widget("UserChanAuthTree", UserChanAuthTree);
UserChanAuthTree->set_model(UserChanAuthModel);
pColumn = Gtk::manage( new Gtk::TreeView::Column("Channels") );
pColumn->pack_start(adminCheckRecord.name);
pColumn->set_expand(true);
UserChanAuthTree->append_column_editable("Select", adminCheckRecord.on);
UserChanAuthTree->append_column(*pColumn);
builder->get_widget("UserInfoSection", UserInfoSection);
builder->get_widget("UserNetworkSection", UserNetworkSection);
builder->get_widget("UserTransmitSection", UserTransmitSection);
builder->get_widget("UserDisplaySection", UserDisplaySection);
builder->get_widget("UserAdminSection", UserAdminSection);
builder->get_widget("UserEditor", UserEditor);
builder->get_widget("UserOwner", combobox);
UserOwnerModel = Gtk::TreeStore::create(UserEditorColumns);
combobox->set_model(UserOwnerModel);
pColumn = Gtk::manage( new Gtk::TreeView::Column("Owners") );
pColumn->pack_start(adminCheckRecord.name);
pColumn->set_expand(true);
combobox->pack_start(adminRecord.name);
builder->get_widget("UserRank", combobox);
UserRankModel = Gtk::TreeStore::create(UserRankColumns);
combobox->set_model(UserRankModel);
combobox->pack_start(adminRecord.name);
builder->get_widget("UserDuplicateIPs", combobox);
UserDuplicateIPsModel = Gtk::TreeStore::create(UserDuplicateIPsColumns);
combobox->set_model(UserDuplicateIPsModel);
combobox->pack_start(adminRecord.name);
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 0; row[adminRecord.name] = "No Limit";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 1; row[adminRecord.name] = "Do Not Allow Duplicates";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 2; row[adminRecord.name] = "2";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 3; row[adminRecord.name] = "3";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 4; row[adminRecord.name] = "4";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 5; row[adminRecord.name] = "5";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 6; row[adminRecord.name] = "6";
row = *(UserDuplicateIPsModel->append());
row[adminRecord.id] = 7; row[adminRecord.name] = "7";
builder->get_widget("UserDefaultChannel", combobox);
UserDefaultChannelModel = Gtk::TreeStore::create(UserDefaultChannelColumns);
combobox->set_model(UserDefaultChannelModel);
combobox->pack_start(adminRecord.name);
renderer = (Gtk::CellRendererText*)(*(combobox->get_cells().begin()));
renderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE;
builder->get_widget("UserAdd", UserAdd);
UserAdd->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::UserAdd_clicked_cb));
builder->get_widget("UserRemove", UserRemove);
UserRemove->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::UserRemove_clicked_cb));
builder->get_widget("UserUpdate", UserUpdate);
UserUpdate->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::UserUpdate_clicked_cb));
currentUserID = 0;
builder->get_widget("UserInfoButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserInfoButton_toggled_cb));
builder->get_widget("UserNetworkButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserNetworkButton_toggled_cb));
builder->get_widget("UserTransmitButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserTransmitButton_toggled_cb));
builder->get_widget("UserDisplayButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserDisplayButton_toggled_cb));
builder->get_widget("UserAdminButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserAdminButton_toggled_cb));
builder->get_widget("UserChanAdminButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserChanAdminButton_toggled_cb));
builder->get_widget("UserChanAuthButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &ManglerAdmin::UserChanAuthButton_toggled_cb));
builder->get_widget("UserTemplate", UserTemplate);
UserTemplateModel = Gtk::TreeStore::create(UserTemplateColumns);
UserTemplate->set_model(UserTemplateModel);
UserTemplate->pack_start(adminRecord.name);
renderer = (Gtk::CellRendererText*)(*(UserTemplate->get_cells().begin()));
renderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE;
UserTemplate->signal_changed().connect(sigc::mem_fun(this, &ManglerAdmin::UserTemplate_changed_cb));
builder->get_widget("UserTemplateLoad", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::UserTemplateLoad_clicked_cb));
builder->get_widget("UserTemplateDelete", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::UserTemplateDelete_clicked_cb));
builder->get_widget("UserTemplateSave", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::UserTemplateSave_clicked_cb));
/* set up the rank editor stuff */
RankEditorModel = Gtk::TreeStore::create(RankEditorColumns);
builder->get_widget("RankTree", RankEditorTree);
RankEditorTree->set_model(RankEditorModel);
RankEditorTree->append_column("Name", rankRecord.name);
RankEditorTree->append_column("Level", rankRecord.level);
RankEditorTree->append_column("Description", rankRecord.description);
RankEditorTree->signal_cursor_changed().connect(sigc::mem_fun(this, &ManglerAdmin::RankEditorTree_cursor_changed_cb));
builder->get_widget("RankEditor", RankEditor);
builder->get_widget("RankAdd", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::RankAdd_clicked_cb));
builder->get_widget("RankRemove", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::RankRemove_clicked_cb));
builder->get_widget("RankUpdate", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::RankUpdate_clicked_cb));
/* set up the ban editor stuff */
BanEditorModel = Gtk::TreeStore::create(BanEditorColumns);
builder->get_widget("BanTree", BanEditorTree);
BanEditorTree->set_model(BanEditorModel);
BanEditorTree->append_column("IP Address", banRecord.ip);
BanEditorTree->append_column("Netmask", banRecord.netmask);
BanEditorTree->append_column("User", banRecord.user);
BanEditorTree->append_column("Admin", banRecord.by);
BanEditorTree->append_column("Reason", banRecord.reason);
BanEditorTree->signal_cursor_changed().connect(sigc::mem_fun(this, &ManglerAdmin::BanEditorTree_cursor_changed_cb));
builder->get_widget("BanEditor", BanEditor);
builder->get_widget("BanNetmask", combobox);
BanNetmaskModel = Gtk::TreeStore::create(adminRecord);
combobox->set_model(BanNetmaskModel);
combobox->pack_start(adminRecord.name);
for (uint32_t ctr = 8; _v3_bitmasks[ctr] != NULL; ctr++) {
Gtk::TreeModel::iterator iter = BanNetmaskModel->append();
(*iter)[adminRecord.id] = ctr;
(*iter)[adminRecord.name] = c_to_ustring(_v3_bitmasks[ctr]);
combobox->set_active(iter);
BanNetmaskDefault = ctr;
}
builder->get_widget("BanAdd", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::BanAdd_clicked_cb));
builder->get_widget("BanRemove", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::BanRemove_clicked_cb));
builder->get_widget("BanUpdate", button);
button->signal_clicked().connect(sigc::mem_fun(this, &ManglerAdmin::BanUpdate_clicked_cb));
/* set up the editor tabs */
clear();
tmpldialog = NULL;
isOpen = false;
}/*}}}*/
ManglerAdmin::~ManglerAdmin() {/*{{{*/
if (tmpldialog) {
delete tmpldialog;
}
}/*}}}*/
void
ManglerAdmin::show(void) {/*{{{*/
adminWindow->set_icon(mangler->icons["tray_icon"]);
adminWindow->present();
if (isOpen) {
permsUpdated(true);
}
}/*}}}*/
void
ManglerAdmin::hide(void) {/*{{{*/
adminWindow->hide();
}/*}}}*/
void
ManglerAdmin::permsUpdated(bool refresh) {/*{{{*/
const v3_permissions *perms = v3_get_permissions();
clearRankEditor();
setWidgetSensitive("RankAdd", RankEditorOpen && perms->edit_rank);
if (isOpen && !refresh) {
return;
}
if (mangler->isAdmin || perms->add_user || perms->del_user) {
UserAdd->set_sensitive(mangler->isAdmin || perms->add_user);
UsersTab->show();
} else {
UsersTab->hide();
}
if (perms->ban_user) {
BansTab->show();
} else {
BansTab->hide();
}
}/*}}}*/
void
ManglerAdmin::adminWindow_show_cb(void) {/*{{{*/
const v3_permissions *perms = v3_get_permissions();
permsUpdated();
if (perms->ban_user) {
v3_admin_ban_list();
}
if (mangler->isAdmin || perms->add_user || perms->del_user) {
UserEditorOpen = true;
v3_userlist_open();
}
if (perms->edit_rank) {
RankEditorOpen = true;
v3_ranklist_open();
}
if (mangler->isAdmin && SrvIsNotUpdating) {
SrvEditorOpen = true;
v3_serverprop_open();
}
loadUserTemplates();
ChannelEditorTree->expand_all();
UserChanAdminTree->expand_all();
UserChanAuthTree->expand_all();
Gtk::TreeModel::iterator iter = ChannelEditorTreeModel->children().begin();
if (iter) {
ChannelEditorTree->set_cursor(ChannelEditorTreeModel->get_path(iter));
}
isOpen = true;
}/*}}}*/
void
ManglerAdmin::adminWindow_hide_cb(void) {/*{{{*/
if (SrvEditorOpen && SrvIsNotUpdating) {
SrvEditorOpen = false;
v3_serverprop_close();
}
if (RankEditorOpen) {
RankEditorOpen = false;
v3_ranklist_close();
}
if (UserEditorOpen) {
UserEditorOpen = false;
v3_userlist_close();
}
ServerTab->hide();
clearUsers();
clearRankEditor();
clearBans();
isOpen = false;
}/*}}}*/
void
ManglerAdmin::queue_resize(Gtk::TreeView *treeview) {/*{{{*/
for (int ctr = 0, cnt = treeview->get_columns().size(); ctr < cnt; ctr++) {
treeview->get_column(ctr)->queue_resize();
}
}/*}}}*/
void
ManglerAdmin::statusbarPush(Glib::ustring msg) {/*{{{*/
AdminStatusbar->push(msg);
StatusbarCount++;
StatusbarTime = time(NULL);
}/*}}}*/
bool
ManglerAdmin::statusbarPop(void) {/*{{{*/
if (StatusbarTime + 3 > ::time(NULL)) return true;
while (StatusbarCount) {
AdminStatusbar->pop();
StatusbarCount--;
}
return true;
}/*}}}*/
void
ManglerAdmin::CloseButton_clicked_cb(void) {/*{{{*/
adminWindow->hide();
}/*}}}*/
void
ManglerAdmin::copyToEntry(const char *widgetName, Glib::ustring src) {/*{{{*/
builder->get_widget(widgetName, entry);
//if (src) entry->set_text(src);
//else entry->set_text("");
entry->set_text(src);
}/*}}}*/
void
ManglerAdmin::copyToSpinbutton(const char *widgetName, uint32_t src) {/*{{{*/
builder->get_widget(widgetName, spinbutton);
spinbutton->set_value(src);
}/*}}}*/
void
ManglerAdmin::copyToCheckbutton(const char *widgetName, bool src) {/*{{{*/
builder->get_widget(widgetName, checkbutton);
checkbutton->set_active(src);
}/*}}}*/
void
ManglerAdmin::copyToCombobox(const char *widgetName, uint32_t src, uint32_t deflt) {/*{{{*/
builder->get_widget(widgetName, combobox);
Glib::RefPtr mdl = combobox->get_model();
Gtk::TreeModel::Children children = mdl->children();
if (! children || ! children.size()) {
combobox->set_sensitive(false);
return;
} else combobox->set_sensitive(true);
Gtk::TreeModel::iterator iter = children.begin();
Gtk::TreeModel::iterator dIter = iter;
while (iter != children.end()) {
if ((*iter)[adminRecord.id] == deflt) dIter = iter;
if ((*iter)[adminRecord.id] == src) break;
iter++;
}
if (iter == children.end()) combobox->set_active(dIter);
else combobox->set_active(iter);
}/*}}}*/
Glib::ustring
ManglerAdmin::getFromEntry(const char *widgetName) {/*{{{*/
builder->get_widget(widgetName, entry);
return entry->get_text();
}/*}}}*/
uint32_t
ManglerAdmin::getFromSpinbutton(const char *widgetName) {/*{{{*/
builder->get_widget(widgetName, spinbutton);
return uint32_t( spinbutton->get_value() );
}/*}}}*/
bool
ManglerAdmin::getFromCheckbutton(const char *widgetName) {/*{{{*/
builder->get_widget(widgetName, checkbutton);
return checkbutton->get_active();
}/*}}}*/
uint32_t
ManglerAdmin::getFromCombobox(const char *widgetName, uint32_t deflt) {/*{{{*/
builder->get_widget(widgetName, combobox);
Gtk::TreeModel::iterator iter = combobox->get_active();
if (iter) return (*iter)[adminRecord.id];
else return deflt;
}/*}}}*/
void
ManglerAdmin::setWidgetSensitive(const char *widgetName, bool widgetSens) {/*{{{*/
Gtk::Widget *w;
builder->get_widget(widgetName, w);
w->set_sensitive(widgetSens);
}/*}}}*/
/* ---------- Server Settings Related Methods ---------- */
void
ManglerAdmin::ServerUpdate_clicked_cb(void) {/*{{{*/
v3_server_prop prop;
memset(&prop, 0, sizeof(v3_server_prop));
strncpy(prop.server_comment, ustring_to_c(getFromEntry("ServerComment")).c_str(), sizeof(prop.server_comment));
prop.chat_filter = getFromCombobox("ServerChatFilter");
prop.channel_order = getFromCombobox("ServerChannelOrdering");
prop.motd_always = getFromCheckbutton("ServerAlwaysDisplayMOTD");
// guest accounts
prop.max_guest = getFromSpinbutton("ServerMaxGuests");
prop.autokick_time = getFromSpinbutton("ServerKickGuests");
prop.autoban_time = getFromSpinbutton("ServerBanGuests");
// inactivity
prop.inactivity_timeout = getFromSpinbutton("ServerTimeout");
prop.inactivity_action = getFromCombobox("ServerAction");
prop.inactivity_channel = getFromCombobox("ServerChannel", 0);
// spam filters
prop.channel_spam_filter.action = getFromCombobox("ServerSpamFilterChannelAction");
prop.channel_spam_filter.interval = getFromSpinbutton("ServerSpamFilterChannelInterval");
prop.channel_spam_filter.times = getFromSpinbutton("ServerSpamFilterChannelTimes");
prop.chat_spam_filter.action = getFromCombobox("ServerSpamFilterChatAction");
prop.chat_spam_filter.interval = getFromSpinbutton("ServerSpamFilterChatInterval");
prop.chat_spam_filter.times = getFromSpinbutton("ServerSpamFilterChatTimes");
prop.comment_spam_filter.action = getFromCombobox("ServerSpamFilterCommentAction");
prop.comment_spam_filter.interval = getFromSpinbutton("ServerSpamFilterCommentInterval");
prop.comment_spam_filter.times = getFromSpinbutton("ServerSpamFilterCommentTimes");
prop.tts_spam_filter.action = getFromCombobox("ServerSpamFilterTTSAction");
prop.tts_spam_filter.interval = getFromSpinbutton("ServerSpamFilterTTSInterval");
prop.tts_spam_filter.times = getFromSpinbutton("ServerSpamFilterTTSTimes");
prop.wave_spam_filter.action = getFromCombobox("ServerSpamFilterWaveAction");
prop.wave_spam_filter.interval = getFromSpinbutton("ServerSpamFilterWaveInterval");
prop.wave_spam_filter.times = getFromSpinbutton("ServerSpamFilterWaveTimes");
// bind filters
prop.tts_bind_filter = getFromCheckbutton("ServerBindFilterTTS");
prop.wave_bind_filter = getFromCheckbutton("ServerBindFilterWave");
// remote status
prop.rem_srv_comment = getFromCheckbutton("ServerRemoteStatusServerComment");
prop.rem_chan_names = getFromCheckbutton("ServerRemoteStatusChannelNames");
prop.rem_chan_comments = getFromCheckbutton("ServerRemoteStatusChannelComments");
prop.rem_user_names = getFromCheckbutton("ServerRemoteStatusUserNames");
prop.rem_user_comments = getFromCheckbutton("ServerRemoteStatusUserComments");
prop.rem_show_login_names = getFromCheckbutton("ServerRemoteStatusUseless");
setWidgetSensitive("ServerVBox", false);
SrvIsNotUpdating = false;
v3_serverprop_update(&prop);
statusbarPush("Sending server properties...");
}/*}}}*/
void
ManglerAdmin::serverSettingsUpdated(v3_server_prop &prop) {/*{{{*/
copyToEntry("ServerComment", c_to_ustring(prop.server_comment));
copyToCombobox("ServerChatFilter", prop.chat_filter, 0);
copyToCombobox("ServerChannelOrdering", prop.channel_order, 0);
copyToCheckbutton("ServerAlwaysDisplayMOTD", prop.motd_always);
// guest accounts
copyToSpinbutton("ServerMaxGuests", prop.max_guest);
copyToSpinbutton("ServerKickGuests", prop.autokick_time);
copyToSpinbutton("ServerBanGuests", prop.autoban_time);
// inactivity
copyToSpinbutton("ServerTimeout", prop.inactivity_timeout);
copyToCombobox("ServerAction", prop.inactivity_action, 0);
copyToCombobox("ServerChannel", prop.inactivity_channel, 0);
// spam filters
copyToCombobox("ServerSpamFilterChannelAction", prop.channel_spam_filter.action, 0);
copyToSpinbutton("ServerSpamFilterChannelInterval", prop.channel_spam_filter.interval);
copyToSpinbutton("ServerSpamFilterChannelTimes", prop.channel_spam_filter.times);
copyToCombobox("ServerSpamFilterChatAction", prop.chat_spam_filter.action, 0);
copyToSpinbutton("ServerSpamFilterChatInterval", prop.chat_spam_filter.interval);
copyToSpinbutton("ServerSpamFilterChatTimes", prop.chat_spam_filter.times);
copyToCombobox("ServerSpamFilterCommentAction", prop.comment_spam_filter.action, 0);
copyToSpinbutton("ServerSpamFilterCommentInterval", prop.comment_spam_filter.interval);
copyToSpinbutton("ServerSpamFilterCommentTimes", prop.comment_spam_filter.times);
copyToCombobox("ServerSpamFilterTTSAction", prop.tts_spam_filter.action, 0);
copyToSpinbutton("ServerSpamFilterTTSInterval", prop.tts_spam_filter.interval);
copyToSpinbutton("ServerSpamFilterTTSTimes", prop.tts_spam_filter.times);
copyToCombobox("ServerSpamFilterWaveAction", prop.wave_spam_filter.action, 0);
copyToSpinbutton("ServerSpamFilterWaveInterval", prop.wave_spam_filter.interval);
copyToSpinbutton("ServerSpamFilterWaveTimes", prop.wave_spam_filter.times);
// bind filters
copyToCheckbutton("ServerBindFilterTTS", prop.tts_bind_filter);
copyToCheckbutton("ServerBindFilterWave", prop.wave_bind_filter);
// remote status
copyToCheckbutton("ServerRemoteStatusServerComment", prop.rem_srv_comment);
copyToCheckbutton("ServerRemoteStatusChannelNames", prop.rem_chan_names);
copyToCheckbutton("ServerRemoteStatusChannelComments", prop.rem_chan_comments);
copyToCheckbutton("ServerRemoteStatusUserNames", prop.rem_user_names);
copyToCheckbutton("ServerRemoteStatusUserComments", prop.rem_user_comments);
copyToCheckbutton("ServerRemoteStatusUseless", prop.rem_show_login_names);
setWidgetSensitive("ServerVBox", true);
SrvIsNotUpdating = true;
ServerTab->show();
}/*}}}*/
void
ManglerAdmin::serverSettingsSendDone(void) {/*{{{*/
statusbarPush("Sending server properties... done.");
v3_serverprop_close();
SrvIsNotUpdating = true;
if ((SrvEditorOpen = isOpen)) {
v3_serverprop_open();
} else {
setWidgetSensitive("ServerVBox", true);
}
}/*}}}*/
/* ---------- Channel Editor Related Methods ---------- */
Glib::RefPtr
adminChannelStore::create() {/*{{{*/
return Glib::RefPtr( new adminChannelStore() );
}/*}}}*/
bool
adminChannelStore::row_draggable_vfunc(const Gtk::TreeModel::Path& path) const {/*{{{*/
adminChannelStore* _this = const_cast(this);
const_iterator iter = _this->get_iter(path);
if (!iter) {
return Gtk::TreeStore::row_draggable_vfunc(path);
}
return (mangler->isAdmin && mangler->admin->channelSortManual && (*iter)[c.id] != 0);
}/*}}}*/
bool
adminChannelStore::row_drop_possible_vfunc(const Gtk::TreeModel::Path& dest, const Gtk::SelectionData& selection_data) const {/*{{{*/
Gtk::TreeModel::Path sel;
Gtk::TreeModel::Path::get_from_selection_data(selection_data, sel);
return (sel.get_depth() == dest.get_depth());
}/*}}}*/
bool
adminChannelStore::drag_data_received_vfunc(const Gtk::TreeModel::Path& dest, const Gtk::SelectionData& selection_data) {/*{{{*/
Gtk::TreeModel::Path sel;
Gtk::TreeModel::Path::get_from_selection_data(selection_data, sel);
if (sel.get_depth() != dest.get_depth()) {
return false;
}
adminChannelStore* _this = const_cast(this);
const_iterator iter;
uint16_t src_id, dest_id;
if (!(iter = _this->get_iter(sel)) || !(src_id = (*iter)[c.id]) ||
!(iter = _this->get_iter(dest)) || !(dest_id = (*iter)[c.id]) || src_id == dest_id) {
return false;
}
v3_force_channel_move(src_id, dest_id);
return false;
}/*}}}*/
void
ManglerAdmin::ChannelTree_cursor_changed_cb() {/*{{{*/
Gtk::TreeModel::iterator iter = ChannelEditorTree->get_selection()->get_selected();
if (!iter) {
return;
}
Gtk::TreeModel::Row row = *iter;
currentChannelID = row[adminRecord.id];
if (currentChannelID) {
// load channel data into editor
v3_channel *channel;
if ((channel = v3_get_channel(currentChannelID))) {
populateChannelEditor(channel);
v3_free_channel(channel);
} else {
fprintf(stderr, "failed to retrieve channel information for channel id %d\n", currentChannelID);
populateChannelEditor(NULL);
currentChannelID = 0;
currentChannelParent = 0;
}
} else {
populateChannelEditor(NULL);
}
// get user permissions
//const v3_permissions *perms = v3_get_permissions();
// enable or disable editor and necessary buttons
bool editAccess( mangler->isAdmin || v3_is_channel_admin(currentChannelID) );
ChannelUpdate->set_sensitive(editAccess && currentChannelID);
ChannelEditor->set_sensitive(currentChannelID);
ChannelRemove->set_sensitive(editAccess && currentChannelID);
ChannelAdd->set_sensitive(editAccess);
}/*}}}*/
Gtk::TreeModel::Row
ManglerAdmin::getChannel(uint32_t id, Gtk::TreeModel::Children children, bool hasCheckbox) {/*{{{*/
Gtk::TreeModel::iterator iter = children.begin();
while (iter != children.end()) {
Gtk::TreeModel::Row row = *iter;
uint32_t rowId = hasCheckbox ? row[adminCheckRecord.id] : row[adminRecord.id];
if (rowId == id) {
return row;
}
if (row.children().size()) {
if (row = getChannel(id, row->children())) {
return row;
}
}
iter++;
}
return *iter;
}/*}}}*/
Glib::ustring
ManglerAdmin::getChannelPathString(uint32_t id, Gtk::TreeModel::Children children) {/*{{{*/
Gtk::TreeModel::iterator iter = children.begin();
while (iter != children.end()) {
Gtk::TreeModel::Row row = *iter;
uint32_t rowId = row[adminRecord.id];
if (rowId == id) {
return row[adminRecord.name];
}
if (row.children().size()) {
Glib::ustring retstr = getChannelPathString(id, row->children());
if (! retstr.empty()) {
if (rowId == 0) return retstr;
else return Glib::ustring::compose("%1 : %2", row[adminRecord.name], retstr);
}
}
iter++;
}
return "";
}/*}}}*/
void
ManglerAdmin::channelUpdated(v3_channel *channel) {/*{{{*/
/* channel editor tree */
Gtk::TreeModel::Row chanrow;
Gtk::TreeModel::iterator iter;
chanrow = getChannel(channel->id, ChannelEditorTreeModel->children());
if (chanrow) {
chanrow[adminRecord.id] = channel->id;
chanrow[adminRecord.name] = c_to_ustring(channel->name);
if (currentChannelID == channel->id) populateChannelEditor(channel);
}
queue_resize(ChannelEditorTree);
/* server inactive "move to" channel combo box */
Gtk::TreeModel::Children siChildren = SrvInactChannelModel->children();
bool found( false );
if (siChildren.size()) {
iter = siChildren.begin();
while (iter != siChildren.end()) {
if ((*iter)[adminRecord.id] == channel->id) {
found = true;
break;
}
iter++;
}
}
if (! found) iter = SrvInactChannelModel->append();
(*iter)[adminRecord.id] = channel->id;
(*iter)[adminRecord.name] = getChannelPathString(channel->id, ChannelEditorTreeModel->children());
/* user default channel combo box */
Gtk::TreeModel::Children udChildren = UserDefaultChannelModel->children();
found = false;
if (udChildren.size()) {
iter = udChildren.begin();
while (iter != udChildren.end()) {
if ((*iter)[adminRecord.id] == channel->id) {
found = true;
break;
}
iter++;
}
}
if (! found) iter = UserDefaultChannelModel->append();
(*iter)[adminRecord.id] = channel->id;
(*iter)[adminRecord.name] = getChannelPathString(channel->id, ChannelEditorTreeModel->children());
/* user channel admin tree */
chanrow = getChannel(channel->id, UserChanAdminModel->children(), true);
if (chanrow) {
chanrow[adminCheckRecord.id] = channel->id;
chanrow[adminCheckRecord.name] = c_to_ustring(channel->name);
}
queue_resize(UserChanAdminTree);
/* user channel auth tree */
chanrow = getChannel(channel->id, UserChanAuthModel->children(), true);
if (chanrow) {
if (channel->protect_mode == 2) {
chanrow[adminCheckRecord.id] = channel->id;
chanrow[adminCheckRecord.name] = c_to_ustring(channel->name);
} else UserChanAuthModel->erase(chanrow);
} else if (channel->protect_mode == 2) {
chanrow = *(UserChanAuthModel->append());
if (chanrow) {
chanrow[adminCheckRecord.id] = channel->id;
chanrow[adminCheckRecord.name] = c_to_ustring(channel->name);
}
}
queue_resize(UserChanAuthTree);
/* update status bar */
statusbarPush(Glib::ustring::compose("Channel %1 (%2) updated.", Glib::ustring::format(channel->id), c_to_ustring(channel->name)));
}/*}}}*/
void
ManglerAdmin::channelRemoved(uint32_t chanid) {/*{{{*/
/* channel editor tree */
Gtk::TreeModel::Row chanrow;
Gtk::TreeModel::iterator iter;
chanrow = getChannel(chanid, ChannelEditorTreeModel->children());
if (chanrow) {
iter = ChannelEditorTree->get_selection()->get_selected();
if (iter && (*iter)[adminRecord.id] == chanrow[adminRecord.id]) {
populateChannelEditor(NULL);
currentChannelID = 0;
currentChannelParent = 0;
}
ChannelEditorTreeModel->erase(chanrow);
}
queue_resize(ChannelEditorTree);
/* server inactive "move to" channel combo box */
Gtk::TreeModel::Children siChildren = SrvInactChannelModel->children();
if (siChildren.size()) {
iter = siChildren.begin();
while (iter != siChildren.end()) {
if ((*iter)[adminRecord.id] == chanid) {
SrvInactChannelModel->erase(*iter);
break;
}
iter++;
}
}
/* user default channel combo box */
Gtk::TreeModel::Children udChildren = UserDefaultChannelModel->children();
if (udChildren.size()) {
iter = udChildren.begin();
while (iter != udChildren.end()) {
if ((*iter)[adminRecord.id] == chanid) {
UserDefaultChannelModel->erase(*iter);
break;
}
iter++;
}
}
/* user channel admin tree */
chanrow = getChannel(chanid, UserChanAdminModel->children());
if (chanrow) UserChanAdminModel->erase(chanrow);
queue_resize(UserChanAdminTree);
/* user channel auth tree */
chanrow = getChannel(chanid, UserChanAuthModel->children());
if (chanrow) UserChanAuthModel->erase(chanrow);
queue_resize(UserChanAuthTree);
/* update status bar */
statusbarPush(Glib::ustring::compose("Channel %1 removed.", Glib::ustring::format(chanid)));
}/*}}}*/
void
ManglerAdmin::channelRemoved(v3_channel *channel) {/*{{{*/
channelRemoved(channel->id);
}/*}}}*/
void
ManglerAdmin::channelAdded(v3_channel *channel) {/*{{{*/
/* channel editor tree */
Gtk::TreeModel::Row parent;
Gtk::TreeModel::iterator channelIter;
Gtk::TreeModel::Row channelRow;
parent = getChannel(channel->parent, ChannelEditorTreeModel->children());
if (parent) {
channelIter = ChannelEditorTreeModel->append(parent.children());
} else {
channelIter = ChannelEditorTreeModel->append();
}
channelRow = *channelIter;
channelRow[adminRecord.id] = channel->id;
channelRow[adminRecord.name] = c_to_ustring(channel->name);
if (ChannelAdded) {
ChannelAdded = false;
if (currentChannelID == 0xffff && c_to_ustring(channel->name) == trimString(getFromEntry("ChannelName"))) {
if (parent) {
ChannelEditorTree->expand_row(ChannelEditorTreeModel->get_path(parent), false);
}
ChannelEditorTree->set_cursor(ChannelEditorTreeModel->get_path(channelIter));
}
}
queue_resize(ChannelEditorTree);
/* server inactive "move to" channel combo box */
channelIter = SrvInactChannelModel->append();
(*channelIter)[adminRecord.id] = channel->id;
(*channelIter)[adminRecord.name] = getChannelPathString(channel->id, ChannelEditorTreeModel->children());
/* user default channel combo box */
channelIter = UserDefaultChannelModel->append();
(*channelIter)[adminRecord.id] = channel->id;
(*channelIter)[adminRecord.name] = getChannelPathString(channel->id, ChannelEditorTreeModel->children());
/* user channel admin tree */
parent = getChannel(channel->parent, UserChanAdminModel->children(), true);
if (parent) {
channelIter = UserChanAdminModel->append(parent.children());
} else {
channelIter = UserChanAdminModel->append();
}
channelRow = *channelIter;
channelRow[adminCheckRecord.id] = channel->id;
channelRow[adminCheckRecord.name] = c_to_ustring(channel->name);
queue_resize(UserChanAdminTree);
/* user channel auth tree */
if (channel->protect_mode == 2) {
parent = getChannel(channel->parent, UserChanAuthModel->children(), true);
if (parent) {
channelIter = UserChanAuthModel->append(parent.children());
} else {
channelIter = UserChanAuthModel->append();
}
channelRow = *channelIter;
channelRow[adminCheckRecord.id] = channel->id;
channelRow[adminCheckRecord.name] = c_to_ustring(channel->name);
}
queue_resize(UserChanAuthTree);
/* update status bar */
statusbarPush(Glib::ustring::compose("Channel %1 (%2) added.", Glib::ustring::format(channel->id), c_to_ustring(channel->name)));
}/*}}}*/
void
ManglerAdmin::populateChannelEditor(const v3_channel *channel) {/*{{{*/
v3_channel c;
::memset(&c, 0, sizeof(v3_channel));
c.channel_codec = 0xffff;
if (channel) {
::memcpy(&c, channel, sizeof(v3_channel));
currentChannelID = c.id;
currentChannelParent = c.parent;
} else {
ChannelUpdate->set_sensitive(false);
ChannelEditor->set_sensitive(false);
ChannelRemove->set_sensitive(false);
}
//fprintf(stderr, "Populate: channel %lu, parent %lu\n", currentChannelID, currentChannelParent);
copyToEntry("ChannelName", c_to_ustring(c.name));
copyToEntry("ChannelPhonetic", c_to_ustring(c.phonetic));
copyToEntry("ChannelComment", c_to_ustring(c.comment));
copyToEntry("ChannelPassword", (c.password_protected) ? " " : "");
copyToCombobox("ChannelProtMode", c.protect_mode, 0);
copyToCombobox("ChannelVoiceMode", c.voice_mode, 0);
copyToCheckbutton("AllowRecording", c.allow_recording);
copyToCheckbutton("AllowCCxmit", c.allow_cross_channel_transmit);
copyToCheckbutton("AllowPaging", c.allow_paging);
copyToCheckbutton("AllowWaveBinds", c.allow_wave_file_binds);
copyToCheckbutton("AllowTTSBinds", c.allow_tts_binds);
copyToCheckbutton("AllowU2Uxmit", c.allow_u2u_transmit);
copyToCheckbutton("AllowPhantoms", c.allow_phantoms);
copyToCheckbutton("AllowGuests", c.allow_guests);
copyToCheckbutton("AllowVoiceTargets", c.allow_voice_target);
copyToCheckbutton("AllowCommandTargets", c.allow_command_target);
copyToCheckbutton("TimerExempt", c.inactive_exempt);
copyToCheckbutton("MuteGuests", c.disable_guest_transmit);
copyToCheckbutton("DisableSoundEvents", c.disable_sound_events);
if (v3_is_licensed()) {
copyToCombobox("ChannelCodec" , c.channel_codec, 4);
if (c.channel_codec != 0xffff) {
copyToCombobox("ChannelFormat", c.channel_format);
}
setWidgetSensitive("ChannelCodecLabel", true);
setWidgetSensitive("ChannelCodec", true);
setWidgetSensitive("ChannelFormatLabel", true);
setWidgetSensitive("ChannelFormat", true);
setWidgetSensitive("AllowVoiceTargets", true);
setWidgetSensitive("AllowCommandTargets", true);
} else {
copyToCombobox("ChannelCodec" , 4);
setWidgetSensitive("ChannelCodecLabel", false);
setWidgetSensitive("ChannelCodec", false);
setWidgetSensitive("ChannelFormatLabel", false);
setWidgetSensitive("ChannelFormat", false);
setWidgetSensitive("AllowVoiceTargets", false);
setWidgetSensitive("AllowCommandTargets", false);
}
builder->get_widget("ChannelEditorLabel", label);
label->set_text("Editing: " + ((channel) ? c_to_ustring(c.name) : "NONE"));
//LoadCodecFormats();
}/*}}}*/
void
ManglerAdmin::ChannelAdd_clicked_cb(void) {/*{{{*/
ChannelEditorTree->get_selection()->unselect_all();
populateChannelEditor(NULL);
copyToCheckbutton("AllowRecording", true);
copyToCheckbutton("AllowCCxmit", true);
copyToCheckbutton("AllowPaging", true);
copyToCheckbutton("AllowWaveBinds", true);
copyToCheckbutton("AllowTTSBinds", true);
copyToCheckbutton("AllowU2Uxmit", true);
copyToCheckbutton("AllowPhantoms", true);
copyToCheckbutton("AllowGuests", true);
bool isLicensed( v3_is_licensed() );
copyToCheckbutton("AllowVoiceTargets", isLicensed);
copyToCheckbutton("AllowCommandTargets", isLicensed);
builder->get_widget("ChannelEditorLabel", label);
label->set_text("Editing: NEW CHANNEL");
currentChannelParent = currentChannelID;
currentChannelID = 0xffff;
//fprintf(stderr, "Add: channel %lu, parent %lu\n", currentChannelID, currentChannelParent);
ChannelAdd->set_sensitive(false);
ChannelRemove->set_sensitive(false);
ChannelEditor->set_sensitive(true);
ChannelUpdate->set_sensitive(true);
}/*}}}*/
void
ManglerAdmin::ChannelRemove_clicked_cb(void) {/*{{{*/
v3_channel *channel = v3_get_channel(currentChannelID);
if (!channel) return;
Gtk::MessageDialog confirmDlg( Glib::ustring::compose("Are you sure you want to remove channel %1 (%2)?", Glib::ustring::format(channel->id), c_to_ustring(channel->name)), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true );
v3_free_channel(channel);
if (confirmDlg.run() == Gtk::RESPONSE_YES) {
v3_channel_remove(currentChannelID);
}
}/*}}}*/
void
ManglerAdmin::ChannelUpdate_clicked_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter;
v3_channel channel;
Glib::ustring password;
::memset(&channel, 0, sizeof(v3_channel));
if (currentChannelID == 0xffff) {
// New Record
channel.id = 0;
ChannelAdded = true;
} else {
channel.id = currentChannelID;
}
channel.parent = currentChannelParent;
//fprintf(stderr, "Update: channel %lu, parent %lu\n", channel.id, channel.parent);
channel.name = ::strdup(ustring_to_c(getFromEntry("ChannelName")).c_str());
channel.phonetic = ::strdup(ustring_to_c(getFromEntry("ChannelPhonetic")).c_str());
channel.comment = ::strdup(ustring_to_c(getFromEntry("ChannelComment")).c_str());
password = trimString(getFromEntry("ChannelPassword"));
if (password.length()) channel.password_protected = 1;
channel.protect_mode = getFromCombobox("ChannelProtMode", 0);
channel.voice_mode = getFromCombobox("ChannelVoiceMode", 0);
channel.allow_recording = getFromCheckbutton("AllowRecording") ? 1 : 0;
channel.allow_cross_channel_transmit = getFromCheckbutton("AllowCCxmit") ? 1 : 0;
channel.allow_paging = getFromCheckbutton("AllowPaging") ? 1 : 0;
channel.allow_wave_file_binds = getFromCheckbutton("AllowWaveBinds") ? 1 : 0;
channel.allow_tts_binds = getFromCheckbutton("AllowTTSBinds") ? 1 : 0;
channel.allow_u2u_transmit = getFromCheckbutton("AllowU2Uxmit") ? 1 : 0;
channel.allow_phantoms = getFromCheckbutton("AllowPhantoms") ? 1 : 0;
channel.allow_guests = getFromCheckbutton("AllowGuests") ? 1 : 0;
channel.allow_voice_target = getFromCheckbutton("AllowVoiceTargets") ? 1 : 0;
channel.allow_command_target = getFromCheckbutton("AllowCommandTargets") ? 1 : 0;
channel.inactive_exempt = getFromCheckbutton("TimerExempt") ? 1 : 0;
channel.disable_guest_transmit = getFromCheckbutton("MuteGuests") ? 1 : 0;
channel.disable_sound_events = getFromCheckbutton("DisableSoundEvents") ? 1 : 0;
if (v3_is_licensed()) {
channel.channel_codec = getFromCombobox("ChannelCodec", 4);
if (channel.channel_codec < 4) {
channel.channel_format = getFromCombobox("ChannelFormat", 0);
} else {
channel.channel_codec = 0xffff;
channel.channel_format = 0xffff;
}
} else {
channel.channel_codec = 0xffff;
channel.channel_format = 0xffff;
}
//fprintf(stderr, "Updating:\nname: %s\nphonetic: %s\ncomment: %s\npassword: %s\n",
// channel.name, channel.phonetic, channel.comment, password.c_str());
v3_channel_update(&channel, ustring_to_c(password).c_str());
::free(channel.name);
::free(channel.phonetic);
::free(channel.comment);
}/*}}}*/
void
ManglerAdmin::channelSort(bool manual) {/*{{{*/
channelSortManual = manual;
if (!manual) {
ChannelEditorTreeModel->set_sort_func(0, sigc::mem_fun(*this, &ManglerAdmin::channelSortFunction));
ChannelEditorTreeModel->set_sort_column(adminRecord.name, Gtk::SORT_ASCENDING);
} else {
ChannelEditorTreeModel->set_sort_func(adminRecord.id, sigc::mem_fun(*this, &ManglerAdmin::channelSortFunction));
ChannelEditorTreeModel->set_sort_column(adminRecord.id, Gtk::SORT_ASCENDING);
}
}/*}}}*/
void
ManglerAdmin::channelResort(void) {/*{{{*/
channelSort(channelSortManual);
}/*}}}*/
int
ManglerAdmin::channelSortFunction(const Gtk::TreeModel::iterator &left, const Gtk::TreeModel::iterator &right) {/*{{{*/
if (!channelSortManual) {
Glib::ustring leftstr = (*left)[adminRecord.name];
Glib::ustring rightstr = (*right)[adminRecord.name];
return natsort(leftstr.c_str(), rightstr.c_str());
} else {
return v3_get_channel_sort((*left)[adminRecord.id], (*right)[adminRecord.id]);
}
}/*}}}*/
void
ManglerAdmin::clearChannels(void) {/*{{{*/
ChannelAdded = false;
ChannelEditorTreeModel->clear();
queue_resize(ChannelEditorTree);
Gtk::TreeModel::Row lobby = *(ChannelEditorTreeModel->append());
lobby[adminRecord.id] = 0;
lobby[adminRecord.name] = "(Lobby)";
currentChannelID = 0;
currentChannelParent = 0;
ChannelUpdate->set_sensitive(false);
ChannelEditor->set_sensitive(false);
ChannelRemove->set_sensitive(false);
ChannelAdd->set_sensitive(false);
SrvInactChannelModel->clear();
lobby = *(SrvInactChannelModel->append());
lobby[adminRecord.id] = 0;
lobby[adminRecord.name] = "(Lobby)";
UserDefaultChannelModel->clear();
lobby = *(UserDefaultChannelModel->append());
lobby[adminRecord.id] = 0;
lobby[adminRecord.name] = "(Lobby)";
UserChanAdminModel->clear();
queue_resize(UserChanAdminTree);
UserChanAuthModel->clear();
queue_resize(UserChanAuthTree);
}/*}}}*/
void
ManglerAdmin::LoadCodecFormats(void) {/*{{{*/
builder->get_widget("ChannelCodec", combobox);
uint16_t c = 4;
Gtk::TreeModel::iterator iter = combobox->get_active();
if (iter) c = (*iter)[adminRecord.id];
builder->get_widget("ChannelFormat", combobox);
combobox->set_sensitive(c < 4);
uint16_t f = 0;
const v3_codec *codec;
Gtk::TreeModel::Row row;
ChannelFormatModel->clear();
while ((codec = v3_get_codec(c, f)) && codec->codec != (uint8_t)-1) {
row = *(ChannelFormatModel->append());
row[adminRecord.id] = f;
row[adminRecord.name] = codec->name;
f++;
}
if (c < 4 && ! combobox->get_active()) {
combobox->set_active(0);
} else {
combobox->set_active(-1);
}
}/*}}}*/
void
ManglerAdmin::ChannelProtMode_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter;
builder->get_widget("ChannelProtMode", combobox);
iter = combobox->get_active();
bool isPassword( iter && (*iter)[adminRecord.id] == 1);
builder->get_widget("ChannelPassword", entry);
entry->set_sensitive(isPassword);
}/*}}}*/
void
ManglerAdmin::ChannelVoiceMode_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter;
builder->get_widget("ChannelVoiceMode", combobox);
iter = combobox->get_active();
bool notNormal( iter && (*iter)[adminRecord.id] );
builder->get_widget("TransmitRank", spinbutton);
spinbutton->set_sensitive(notNormal);
}/*}}}*/
/* ---------- User Editor Related Methods ---------- */
Gtk::TreeModel::Row
ManglerAdmin::getAccount(uint32_t id, Gtk::TreeModel::Children children) {/*{{{*/
Gtk::TreeModel::iterator iter = children.begin();
while (iter != children.end()) {
if ((*iter)[adminRecord.id] == id) break;
iter++;
}
return *iter;
}/*}}}*/
void
ManglerAdmin::accountUpdated(v3_account *account) {/*{{{*/
/* main user list */
Gtk::TreeModel::Row acct;
acct = getAccount(account->perms.account_id, UserEditorTreeModel->children());
if (! acct) return;
acct[adminRecord.name] = c_to_ustring(account->username);
/* User Owner combo box */
acct = getAccount(account->perms.account_id, UserOwnerModel->children());
if (acct) {
if (account->perms.srv_admin || account->perms.add_user) {
/* update name in owner list */
acct[adminRecord.name] = c_to_ustring(account->username);
} else {
/* needs to be removed, no longer an admin */
UserOwnerModel->erase(acct);
}
} else if (account->perms.srv_admin || account->perms.add_user) {
/* needs to be added to owner list */
acct = *(UserOwnerModel->append());
acct[adminRecord.id] = account->perms.account_id;
acct[adminRecord.name] = c_to_ustring(account->username);
}
if (account->perms.account_id == currentUserID) populateUserEditor(account);
queue_resize(UserEditorTree);
/* update status bar */
statusbarPush(Glib::ustring::compose("User %1 (%2) updated.", Glib::ustring::format(account->perms.account_id), c_to_ustring(account->username)));
}/*}}}*/
void
ManglerAdmin::accountAdded(v3_account *account) {/*{{{*/
/* main user list */
Gtk::TreeModel::iterator iter;
Gtk::TreeModel::Row acct;
iter = UserEditorTreeModel->append();
acct = *iter;
acct[adminRecord.id] = account->perms.account_id;
acct[adminRecord.name] = c_to_ustring(account->username);
/* User Owner combo box */
if (account->perms.srv_admin || account->perms.add_user) {
/* needs to be added to owner list */
acct = *(UserOwnerModel->append());
acct[adminRecord.id] = account->perms.account_id;
acct[adminRecord.name] = c_to_ustring(account->username);
}
if (currentUserID == 0xffff && c_to_ustring(account->username) == trimString(getFromEntry("UserLogin"))) {
UserEditorTree->set_cursor(UserEditorTreeModel->get_path(iter));
}
queue_resize(UserEditorTree);
/* update status bar */
statusbarPush(Glib::ustring::compose("User %1 (%2) added.", Glib::ustring::format(account->perms.account_id), c_to_ustring(account->username)));
}/*}}}*/
void
ManglerAdmin::accountRemoved(uint32_t acctid) {/*{{{*/
/* main user list */
Gtk::TreeModel::Row acct;
Gtk::TreeModel::iterator iter;
acct = getAccount(acctid, UserEditorTreeModel->children());
if (acct) {
iter = UserEditorTree->get_selection()->get_selected();
if (iter && (*iter)[adminRecord.id] == acct[adminRecord.id]) {
populateUserEditor(NULL);
currentUserID = 0;
}
UserEditorTreeModel->erase(acct);
}
queue_resize(UserEditorTree);
/* User Owner combo box */
acct = getAccount(acctid, UserOwnerModel->children());
if (acct) UserOwnerModel->erase(acct);
/* update status bar */
statusbarPush(Glib::ustring::compose("User %1 removed.", Glib::ustring::format(acctid)));
}/*}}}*/
void
ManglerAdmin::accountRemoved(v3_account *account) {/*{{{*/
if (account) accountRemoved(account->perms.account_id);
}/*}}}*/
void
ManglerAdmin::UserTree_cursor_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = UserEditorTree->get_selection()->get_selected();
if (!iter) {
return;
}
Gtk::TreeModel::Row row = *iter;
currentUserID = row[adminRecord.id];
if (currentUserID) {
// load user data into editor
v3_account *account;
if ((account = v3_get_account(currentUserID))) {
populateUserEditor(account);
v3_free_account(account);
} else {
fprintf(stderr, "failed to retrieve user information for account id %d\n", currentUserID);
populateUserEditor(NULL);
currentUserID = 0;
}
} else {
populateUserEditor(NULL);
}
// get user permissions
const v3_permissions *perms = v3_get_permissions();
// enable or disable editor and necessary buttons
bool editAccess( mangler->isAdmin );
UserUpdate->set_sensitive((editAccess || perms->add_user) && currentUserID);
UserEditor->set_sensitive(currentUserID);
UserRemove->set_sensitive((editAccess || perms->del_user) && currentUserID);
UserAdd->set_sensitive(editAccess || perms->add_user);
}/*}}}*/
void
ManglerAdmin::populateUserEditor(const v3_account *account, bool isTemplate) {/*{{{*/
v3_account a;
::memset(&a, 0, sizeof(v3_account));
bool isLicensed( v3_is_licensed() );
if (!isTemplate) {
if (account) {
::memcpy(&a, account, sizeof(v3_account));
setWidgetSensitive("UserLogin", false);
} else {
setWidgetSensitive("UserLogin", true);
UserUpdate->set_sensitive(false);
UserEditor->set_sensitive(false);
UserRemove->set_sensitive(false);
}
copyToEntry("UserLogin", c_to_ustring(a.username));
copyToEntry("UserPassword", (a.perms.account_id > 1) ? " " : "");
setWidgetSensitive("UserPassword", a.perms.account_id != 1);
copyToCombobox("UserRank", a.perms.rank_id, 0);
copyToCombobox("UserOwner", 0);
Glib::ustring ownerName = c_to_ustring(a.owner);
if (ownerName.length()) {
Gtk::TreeModel::iterator iter = UserOwnerModel->children().begin();
while (iter != UserOwnerModel->children().end()) {
if ((*iter)[adminRecord.name] == ownerName) {
copyToCombobox("UserOwner", (*iter)[adminRecord.id], 0);
break;
}
iter++;
}
}
Gtk::TextView *textview;
builder->get_widget("UserNotes", textview);
textview->get_buffer()->set_text(c_to_ustring(a.notes));
} else if (account) {
::memcpy(&a, account, sizeof(v3_account));
}
copyToCheckbutton("UserLocked", a.perms.lock_acct);
copyToEntry("UserLockedReason", c_to_ustring(a.lock_reason));
copyToCheckbutton("UserInReservedList", a.perms.in_reserve_list);
copyToCheckbutton("UserReceiveBroadcasts", a.perms.recv_bcast);
copyToCheckbutton("UserAddPhantoms", a.perms.add_phantom);
copyToCheckbutton("UserAllowRecord", a.perms.record);
copyToCheckbutton("UserIgnoreTimers", a.perms.inactive_exempt);
copyToCheckbutton("UserSendComplaints", a.perms.send_complaint);
copyToCheckbutton("UserReceiveComplaints", a.perms.recv_complaint);
copyToCombobox("UserDuplicateIPs", a.perms.dupe_ip, 0);
copyToCheckbutton("UserSwitchChannels", a.perms.switch_chan);
copyToCombobox("UserDefaultChannel", a.perms.dfl_chan);
copyToCheckbutton("UserBroadcast", a.perms.bcast);
copyToCheckbutton("UserBroadcastLobby", a.perms.bcast_lobby);
copyToCheckbutton("UserBroadcastU2U", a.perms.bcast_user);
copyToCheckbutton("UserBroadcastxChan", a.perms.bcast_x_chan);
copyToCheckbutton("UserSendTTSBinds", a.perms.send_tts_bind);
copyToCheckbutton("UserSendWaveBinds", a.perms.send_wav_bind);
copyToCheckbutton("UserSendPages", a.perms.send_page);
copyToCheckbutton("UserSetPhonetic", a.perms.set_phon_name);
copyToCheckbutton("UserSendComment", a.perms.send_comment);
copyToCheckbutton("UserGenCommentSounds", a.perms.gen_comment_snds);
copyToCheckbutton("UserEventSounds", a.perms.event_snds);
copyToCheckbutton("UserMuteGlobally", a.perms.mute_glbl);
copyToCheckbutton("UserMuteOthers", a.perms.mute_other);
copyToCheckbutton("UserGlobalChat", a.perms.glbl_chat);
copyToCheckbutton("UserPrivateChat", a.perms.start_priv_chat);
setWidgetSensitive("UserPrivateChat", isLicensed);
copyToCheckbutton("UserEqOut", a.perms.eq_out);
copyToCheckbutton("UserSeeGuests", a.perms.see_guest);
copyToCheckbutton("UserSeeNonGuests", a.perms.see_nonguest);
copyToCheckbutton("UserSeeMOTD", a.perms.see_motd);
copyToCheckbutton("UserSeeServerComment", a.perms.see_srv_comment);
copyToCheckbutton("UserSeeChannelList", a.perms.see_chan_list);
copyToCheckbutton("UserSeeChannelComments", a.perms.see_chan_comment);
copyToCheckbutton("UserSeeUserComments", a.perms.see_user_comment);
copyToCheckbutton("UserServerAdmin", a.perms.srv_admin);
copyToCheckbutton("UserRemoveUsers", a.perms.del_user);
copyToCheckbutton("UserAddUsers", a.perms.add_user);
copyToCheckbutton("UserBanUsers", a.perms.ban_user);
copyToCheckbutton("UserKickUsers", a.perms.kick_user);
copyToCheckbutton("UserMoveUsers", a.perms.move_user);
copyToCheckbutton("UserAssignChanAdmin", a.perms.assign_chan_admin);
copyToCheckbutton("UserAssignRank", a.perms.assign_rank);
copyToCheckbutton("UserEditRanks", a.perms.edit_rank);
copyToCheckbutton("UserEditMOTD", a.perms.edit_motd);
copyToCheckbutton("UserEditGuestMOTD", a.perms.edit_guest_motd);
copyToCheckbutton("UserIssueRcon", a.perms.issue_rcon_cmd);
copyToCheckbutton("UserEditVoiceTargets", a.perms.edit_voice_target);
setWidgetSensitive("UserEditVoiceTargets", isLicensed);
copyToCheckbutton("UserEditCommandTargets", a.perms.edit_command_target);
setWidgetSensitive("UserEditCommandTargets", isLicensed);
copyToCheckbutton("UserAssignReserved", a.perms.assign_reserved);
if (!isTemplate) {
setAdminCheckTree(UserChanAdminModel->children(), a.chan_admin, a.chan_admin_count);
setAdminCheckTree(UserChanAuthModel->children(), a.chan_auth, a.chan_auth_count);
builder->get_widget("UserEditorLabel", label);
label->set_text("Editing: " + ((account) ? c_to_ustring(a.username) : "NONE"));
}
}/*}}}*/
void
ManglerAdmin::setAdminCheckTree(Gtk::TreeModel::Children children, uint16_t *chanids, int chan_count) {/*{{{*/
Gtk::TreeModel::iterator iter = children.begin();
Gtk::TreeModel::Row row;
uint32_t rowId;
int i;
bool found;
while (iter != children.end()) {
row = *iter;
rowId = row[adminCheckRecord.id];
found = false;
for (i = 0; i < chan_count; ++i) {
if (chanids[i] == rowId) {
found = true;
break;
}
}
row[adminCheckRecord.on] = found;
if (row.children().size()) setAdminCheckTree(row->children(), chanids, chan_count);
iter++;
}
}/*}}}*/
void
ManglerAdmin::getAdminCheckTree(Gtk::TreeModel::Children children, std::vector &chanids) {/*{{{*/
Gtk::TreeModel::iterator iter = children.begin();
Gtk::TreeModel::Row row;
uint32_t rowId;
bool rowOn;
while (iter != children.end()) {
row = *iter;
rowId = row[adminCheckRecord.id];
rowOn = row[adminCheckRecord.on];
if (rowOn) chanids.push_back(rowId);
if (row.children().size()) getAdminCheckTree(row->children(), chanids);
iter++;
}
}/*}}}*/
void
ManglerAdmin::getAdminCheckTree(Gtk::TreeModel::Children children, uint16_t *&chanids, int &chan_count) {/*{{{*/
std::vector chanvec;
getAdminCheckTree(children, chanvec);
chan_count = chanvec.size();
if (chan_count) {
chanids = (uint16_t*)::malloc(sizeof(uint16_t) * chanvec.size());
if (chanids) {
for (int i = 0; i < chan_count; ++i) chanids[i] = chanvec[i];
} else chan_count = 0; // failed malloc
} else chanids = NULL;
}/*}}}*/
void
ManglerAdmin::UserAdd_clicked_cb(void) {/*{{{*/
UserEditorTree->get_selection()->unselect_all();
v3_account a;
memset(&a, 0, sizeof(v3_account));
a.perms.recv_bcast = true;
a.perms.add_phantom = true;
a.perms.record = true;
a.perms.send_complaint = true;
a.perms.switch_chan = true;
a.perms.bcast = true;
a.perms.bcast_lobby = true;
a.perms.bcast_user = true;
a.perms.bcast_x_chan = true;
a.perms.send_tts_bind = true;
a.perms.send_wav_bind = true;
a.perms.send_page = true;
a.perms.set_phon_name = true;
a.perms.send_comment = true;
a.perms.gen_comment_snds = true;
a.perms.event_snds = true;
a.perms.glbl_chat = true;
a.perms.start_priv_chat = true;
a.perms.see_guest = true;
a.perms.see_nonguest = true;
a.perms.see_motd = true;
a.perms.see_srv_comment = true;
a.perms.see_chan_list = true;
a.perms.see_chan_comment = true;
a.perms.see_user_comment = true;
populateUserEditor(NULL);
populateUserEditor(&a, true);
builder->get_widget("UserEditorLabel", label);
label->set_text("Editing: NEW USER");
currentUserID = 0xffff;
// enable or disable editor and necessary buttons
UserUpdate->set_sensitive(true);
UserEditor->set_sensitive(true);
UserRemove->set_sensitive(false);
UserAdd->set_sensitive(false);
}/*}}}*/
void
ManglerAdmin::UserRemove_clicked_cb(void) {/*{{{*/
v3_account *account = v3_get_account(currentUserID);
if (!account) return;
Gtk::MessageDialog confirmDlg( Glib::ustring::compose("Are you sure you want to remove user %1 (%2)?", Glib::ustring::format(account->perms.account_id), c_to_ustring(account->username)), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true );
v3_free_account(account);
if (confirmDlg.run() == Gtk::RESPONSE_YES) {
v3_userlist_remove(currentUserID);
}
}/*}}}*/
void
ManglerAdmin::UserUpdate_clicked_cb(void) {/*{{{*/
v3_account account;
::memset(&account, 0, sizeof(v3_account));
account.perms.account_id = (currentUserID == 0xffff) ? 0 : currentUserID;
account.username = ::strdup(ustring_to_c(getFromEntry("UserLogin")).c_str());
Glib::ustring password = trimString(getFromEntry("UserPassword"));
if (password.length()) {
_v3_hash_password((uint8_t *)ustring_to_c(password).c_str(), (uint8_t *)account.perms.hash_password);
}
account.perms.rank_id = getFromCombobox("UserRank", 0);
uint16_t ownerID = getFromCombobox("UserOwner", 0);
if (ownerID) {
Gtk::TreeModel::Row ownerRow = getAccount(ownerID, UserEditorTreeModel->children());
Glib::ustring ownerName = ownerRow[adminRecord.name];
account.owner = ::strdup(ustring_to_c(ownerName).c_str());
} else {
account.owner = ::strdup("");
}
Gtk::TextView *textview;
builder->get_widget("UserNotes", textview);
account.notes = ::strdup(ustring_to_c(textview->get_buffer()->get_text()).c_str());
account.perms.lock_acct = getFromCheckbutton("UserLocked");
account.lock_reason = ::strdup(ustring_to_c(getFromEntry("UserLockedReason")).c_str());
account.perms.in_reserve_list = getFromCheckbutton("UserInReservedList");
account.perms.recv_bcast = getFromCheckbutton("UserReceiveBroadcasts");
account.perms.add_phantom = getFromCheckbutton("UserAddPhantoms");
account.perms.record = getFromCheckbutton("UserAllowRecord");
account.perms.inactive_exempt = getFromCheckbutton("UserIgnoreTimers");
account.perms.send_complaint = getFromCheckbutton("UserSendComplaints");
account.perms.recv_complaint = getFromCheckbutton("UserReceiveComplaints");
account.perms.dupe_ip = getFromCombobox("UserDuplicateIPs", 0);
account.perms.switch_chan = getFromCheckbutton("UserSwitchChannels");
account.perms.dfl_chan = getFromCombobox("UserDefaultChannel");
account.perms.bcast = getFromCheckbutton("UserBroadcast");
account.perms.bcast_lobby = getFromCheckbutton("UserBroadcastLobby");
account.perms.bcast_user = getFromCheckbutton("UserBroadcastU2U");
account.perms.bcast_x_chan = getFromCheckbutton("UserBroadcastxChan");
account.perms.send_tts_bind = getFromCheckbutton("UserSendTTSBinds");
account.perms.send_wav_bind = getFromCheckbutton("UserSendWaveBinds");
account.perms.send_page = getFromCheckbutton("UserSendPages");
account.perms.set_phon_name = getFromCheckbutton("UserSetPhonetic");
account.perms.send_comment = getFromCheckbutton("UserSendComment");
account.perms.gen_comment_snds = getFromCheckbutton("UserGenCommentSounds");
account.perms.event_snds = getFromCheckbutton("UserEventSounds");
account.perms.mute_glbl = getFromCheckbutton("UserMuteGlobally");
account.perms.mute_other = getFromCheckbutton("UserMuteOthers");
account.perms.glbl_chat = getFromCheckbutton("UserGlobalChat");
account.perms.start_priv_chat = getFromCheckbutton("UserPrivateChat");
account.perms.eq_out = getFromCheckbutton("UserEqOut");
account.perms.see_guest = getFromCheckbutton("UserSeeGuests");
account.perms.see_nonguest = getFromCheckbutton("UserSeeNonGuests");
account.perms.see_motd = getFromCheckbutton("UserSeeMOTD");
account.perms.see_srv_comment = getFromCheckbutton("UserSeeServerComment");
account.perms.see_chan_list = getFromCheckbutton("UserSeeChannelList");
account.perms.see_chan_comment = getFromCheckbutton("UserSeeChannelComments");
account.perms.see_user_comment = getFromCheckbutton("UserSeeUserComments");
account.perms.srv_admin = getFromCheckbutton("UserServerAdmin");
account.perms.del_user = getFromCheckbutton("UserRemoveUsers");
account.perms.add_user = getFromCheckbutton("UserAddUsers");
account.perms.ban_user = getFromCheckbutton("UserBanUsers");
account.perms.kick_user = getFromCheckbutton("UserKickUsers");
account.perms.move_user = getFromCheckbutton("UserMoveUsers");
account.perms.assign_chan_admin = getFromCheckbutton("UserAssignChanAdmin");
account.perms.assign_rank = getFromCheckbutton("UserAssignRank");
account.perms.edit_rank = getFromCheckbutton("UserEditRanks");
account.perms.edit_motd = getFromCheckbutton("UserEditMOTD");
account.perms.edit_guest_motd = getFromCheckbutton("UserEditGuestMOTD");
account.perms.issue_rcon_cmd = getFromCheckbutton("UserIssueRcon");
account.perms.edit_voice_target = getFromCheckbutton("UserEditVoiceTargets");
account.perms.edit_command_target = getFromCheckbutton("UserEditCommandTargets");
account.perms.assign_reserved = getFromCheckbutton("UserAssignReserved");
getAdminCheckTree(UserChanAdminModel->children(), account.chan_admin, account.chan_admin_count);
getAdminCheckTree(UserChanAuthModel->children(), account.chan_auth, account.chan_auth_count);
v3_userlist_update(&account);
::free(account.username);
::free(account.owner);
::free(account.notes);
::free(account.lock_reason);
if (account.chan_admin_count) ::free(account.chan_admin);
if (account.chan_auth_count) ::free(account.chan_auth);
}/*}}}*/
void
ManglerAdmin::UserInfoButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserInfoButton", togglebutton);
builder->get_widget("UserInfoArrow", arrow);
if (togglebutton->get_active()) {
UserInfoSection->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserInfoSection->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::UserNetworkButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserNetworkButton", togglebutton);
builder->get_widget("UserNetworkArrow", arrow);
if (togglebutton->get_active()) {
UserNetworkSection->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserNetworkSection->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::UserTransmitButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserTransmitButton", togglebutton);
builder->get_widget("UserTransmitArrow", arrow);
if (togglebutton->get_active()) {
UserTransmitSection->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserTransmitSection->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::UserDisplayButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserDisplayButton", togglebutton);
builder->get_widget("UserDisplayArrow", arrow);
if (togglebutton->get_active()) {
UserDisplaySection->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserDisplaySection->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::UserAdminButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserAdminButton", togglebutton);
builder->get_widget("UserAdminArrow", arrow);
if (togglebutton->get_active()) {
UserAdminSection->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserAdminSection->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::UserChanAdminButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserChanAdminButton", togglebutton);
builder->get_widget("UserChanAdminArrow", arrow);
if (togglebutton->get_active()) {
UserChanAdminTree->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserChanAdminTree->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::UserChanAuthButton_toggled_cb(void) {/*{{{*/
builder->get_widget("UserChanAuthButton", togglebutton);
builder->get_widget("UserChanAuthArrow", arrow);
if (togglebutton->get_active()) {
UserChanAuthTree->show();
arrow->set(Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
} else {
UserChanAuthTree->hide();
arrow->set(Gtk::ARROW_RIGHT, Gtk::SHADOW_NONE);
}
}/*}}}*/
void
ManglerAdmin::clearUsers(void) {/*{{{*/
UserEditorTreeModel->clear();
queue_resize(UserEditorTree);
populateUserEditor(NULL);
currentUserID = 0;
UserUpdate->set_sensitive(false);
UserEditor->set_sensitive(false);
UserRemove->set_sensitive(false);
UserAdd->set_sensitive(false);
UserOwnerModel->clear();
Gtk::TreeModel::Row row = *(UserOwnerModel->append());
row[adminRecord.id] = 0;
row[adminRecord.name] = "(None)";
}/*}}}*/
/* user editor 'profile' methods */
void
ManglerAdmin::loadUserTemplates(void) {/*{{{*/
tmpldir = ManglerConfig::confdir() + "/templates";
UserTemplateModel->clear();
Gtk::TreeStore::Row row = *(UserTemplateModel->append());
row[adminRecord.id] = 0;
row[adminRecord.name] = "Default Admin";
row = *(UserTemplateModel->append());
row[adminRecord.id] = 1;
row[adminRecord.name] = "Default User";
row = *(UserTemplateModel->append());
row[adminRecord.id] = 2;
row[adminRecord.name] = "(None)";
UserTemplate->set_active(2);
DIR *testdir;
if ((testdir = opendir(tmpldir.c_str()))) {
closedir(testdir);
} else if (mkdir(tmpldir.c_str(), 0700)) {
tmpldir = "";
return;
}
Glib::Dir dir(tmpldir);
int ctr = 3;
for (Glib::DirIterator iter = dir.begin(); iter != dir.end(); iter++) {
row = *(UserTemplateModel->append());
row[adminRecord.id] = ctr++;
row[adminRecord.name] = *iter;
}
}/*}}}*/
void
ManglerAdmin::UserTemplate_changed_cb(void) {/*{{{*/
Gtk::TreeStore::iterator iter = UserTemplate->get_active();
setWidgetSensitive("UserTemplateDelete", tmpldir.length() && iter && (*iter)[adminRecord.id] > 2);
}/*}}}*/
void
ManglerAdmin::UserTemplateLoad_clicked_cb(void) {/*{{{*/
Gtk::TreeStore::iterator iter = UserTemplate->get_active();
if (!iter) {
return;
}
uint32_t id = (*iter)[adminRecord.id];
Glib::ustring name = (*iter)[adminRecord.name];
v3_account a;
memset(&a, 0, sizeof(v3_account));
if (id < 2) {
a.perms.recv_bcast = true;
a.perms.add_phantom = true;
a.perms.record = true;
a.perms.send_complaint = true;
a.perms.switch_chan = true;
a.perms.bcast = true;
a.perms.bcast_lobby = true;
a.perms.bcast_user = true;
a.perms.bcast_x_chan = true;
a.perms.send_tts_bind = true;
a.perms.send_wav_bind = true;
a.perms.send_page = true;
a.perms.set_phon_name = true;
a.perms.send_comment = true;
a.perms.gen_comment_snds = true;
a.perms.event_snds = true;
a.perms.glbl_chat = true;
a.perms.start_priv_chat = true;
a.perms.see_guest = true;
a.perms.see_nonguest = true;
a.perms.see_motd = true;
a.perms.see_srv_comment = true;
a.perms.see_chan_list = true;
a.perms.see_chan_comment = true;
a.perms.see_user_comment = true;
if (id == 0) {
a.perms.in_reserve_list = true;
a.perms.recv_complaint = true;
a.perms.add_user = true;
a.perms.del_user = true;
a.perms.ban_user = true;
a.perms.kick_user = true;
a.perms.move_user = true;
a.perms.assign_chan_admin = true;
}
} else if (id > 2 && tmpldir.length() && name.length()) {
iniFile tmplfile(tmpldir + "/" + name, true, false);
if (!tmplfile.contains("Profile")) {
statusbarPush("Error: No 'Profile' section found in template.");
return;
}
iniSection &tmpl(tmplfile["Profile"]);
a.perms.lock_acct = tmpl["Locked"].toBool();
a.perms.in_reserve_list = tmpl["Reserved"].toBool();
a.perms.recv_bcast = tmpl["RecvStreams"].toBool();
a.perms.add_phantom = tmpl["Phantoms"].toBool();
a.perms.record = tmpl["Record"].toBool();
a.perms.inactive_exempt = tmpl["IgnoreInactivity"].toBool();
a.perms.send_complaint = tmpl["SendComplaints"].toBool();
a.perms.recv_complaint = tmpl["RecvComplaints"].toBool();
a.perms.switch_chan = tmpl["SwitchChannels"].toBool();
a.lock_reason = ::strdup(ustring_to_c(tmpl["LockedReason"].toUString()).c_str());
a.perms.dfl_chan = v3_get_channel_id(ustring_to_c(tmpl["DefChan"].toUString()).c_str());
a.perms.dupe_ip = tmpl["DuplicateIPs"].toInt();
a.perms.bcast = tmpl["Broadcast"].toBool();
a.perms.bcast_lobby = tmpl["BroadcastLobby"].toBool();
a.perms.bcast_user = tmpl["BroadcastU2U"].toBool();
a.perms.bcast_x_chan = tmpl["BroadcastCrossChannel"].toBool();
a.perms.send_tts_bind = tmpl["SendTTS"].toBool();
a.perms.send_wav_bind = tmpl["SendWave"].toBool();
a.perms.send_page = tmpl["SendPages"].toBool();
a.perms.set_phon_name = tmpl["SetPhonetic"].toBool();
a.perms.send_comment = tmpl["SendComments"].toBool();
a.perms.gen_comment_snds = tmpl["CommentSounds"].toBool();
a.perms.event_snds = tmpl["EventSounds"].toBool();
a.perms.mute_glbl = tmpl["MuteGlobally"].toBool();
a.perms.mute_other = tmpl["MuteOthersPTT"].toBool();
a.perms.glbl_chat = tmpl["Chat"].toBool();
a.perms.start_priv_chat = tmpl["InitPrivateChat"].toBool();
a.perms.eq_out = tmpl["Equalizer"].toBool();
a.perms.see_guest = tmpl["SeeGuest"].toBool();
a.perms.see_nonguest = tmpl["SeeNonGuest"].toBool();
a.perms.see_motd = tmpl["SeeMotd"].toBool();
a.perms.see_srv_comment = tmpl["SeeServerComment"].toBool();
a.perms.see_chan_list = tmpl["SeeChannels"].toBool();
a.perms.see_chan_comment = tmpl["SeeChannelComments"].toBool();
a.perms.see_user_comment = tmpl["SeeUserComments"].toBool();
a.perms.srv_admin = tmpl["ServerAdmin"].toBool();
a.perms.add_user = tmpl["AddUsers"].toBool();
a.perms.del_user = tmpl["DeleteUsers"].toBool();
a.perms.ban_user = tmpl["BanUsers"].toBool();
a.perms.kick_user = tmpl["KickUsers"].toBool();
a.perms.move_user = tmpl["MoveUsers"].toBool();
a.perms.assign_chan_admin = tmpl["EditChanAdmins"].toBool();
a.perms.edit_rank = tmpl["EditRanks"].toBool();
a.perms.edit_motd = tmpl["EditMotd"].toBool();
a.perms.edit_guest_motd = tmpl["EditGuestMotd"].toBool();
a.perms.issue_rcon_cmd = tmpl["RCon"].toBool();
a.perms.edit_voice_target = tmpl["GroupEditVoice"].toBool();
a.perms.edit_command_target = tmpl["GroupEditCmd"].toBool();
a.perms.assign_rank = tmpl["RankAssign"].toBool();
a.perms.assign_reserved = tmpl["ReservedAssign"].toBool();
}
populateUserEditor(&a, true);
if (a.lock_reason) {
::free(a.lock_reason);
}
statusbarPush("Loaded '" + name + "' template.");
}/*}}}*/
void
ManglerAdmin::UserTemplateDelete_clicked_cb(void) {/*{{{*/
Gtk::TreeStore::iterator iter = UserTemplate->get_active();
if (!iter || tmpldir.empty()) {
return;
}
Glib::ustring name = (*iter)[adminRecord.name];
Gtk::MessageDialog confirm("Are you sure you want to delete \"" + name + "\"?",
true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
if (confirm.run() == Gtk::RESPONSE_YES) {
unlink(Glib::ustring(tmpldir + "/" + name).c_str());
loadUserTemplates();
}
}/*}}}*/
void
ManglerAdmin::UserTemplateSave_clicked_cb(void) {/*{{{*/
if (!tmpldialog) {
tmpldialog = new Gtk::FileChooserDialog("Save User Template", Gtk::FILE_CHOOSER_ACTION_SAVE);
tmpldialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
tmpldialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
tpl_filter.set_name("Ventrilo User Editor Profile (*.vuep, *.ini)");
tpl_filter.add_pattern("*.vuep");
tpl_filter.add_pattern("*.ini");
tmpldialog->add_filter(tpl_filter);
all_filter.set_name("All Files");
all_filter.add_pattern("*");
tmpldialog->add_filter(all_filter);
if (tmpldir.length()) {
tmpldialog->set_current_folder(tmpldir);
}
}
int result = tmpldialog->run();
tmpldialog->hide();
if (result != Gtk::RESPONSE_OK) {
return;
}
Glib::ustring filename = tmpldialog->get_filename();
if (tmpldialog->get_filter() == &tpl_filter) {
Glib::PatternSpec vuep("*.vuep"), ini("*.ini");
if (!vuep.match(filename) && !ini.match(filename)) {
filename.append(".vuep");
}
}
Glib::ustring name = filename.substr(tmpldialog->get_current_folder().length() + 1);
char *path = v3_get_channel_path(getFromCombobox("UserDefaultChannel", 0));
iniFile tmplfile(filename, false, false);
iniSection &tmpl(tmplfile["Profile"]);
tmpl["Locked"] = (int)getFromCheckbutton("UserLocked");
tmpl["Reserved"] = (int)getFromCheckbutton("UserInReservedList");
tmpl["RecvStreams"] = (int)getFromCheckbutton("UserReceiveBroadcasts");
tmpl["Phantoms"] = (int)getFromCheckbutton("UserAddPhantoms");
tmpl["Record"] = (int)getFromCheckbutton("UserAllowRecord");
tmpl["IgnoreInactivity"] = (int)getFromCheckbutton("UserIgnoreTimers");
tmpl["SendComplaints"] = (int)getFromCheckbutton("UserSendComplaints");
tmpl["RecvComplaints"] = (int)getFromCheckbutton("UserReceiveComplaints");
tmpl["SwitchChannels"] = (int)getFromCheckbutton("UserSwitchChannels");
tmpl["LockedReason"] = getFromEntry("UserLockedReason");
tmpl["DefChan"] = c_to_ustring(path);
tmpl["DuplicateIPs"] = (int)getFromCombobox("UserDuplicateIPs", 0);
tmpl["Broadcast"] = (int)getFromCheckbutton("UserBroadcast");
tmpl["BroadcastLobby"] = (int)getFromCheckbutton("UserBroadcastLobby");
tmpl["BroadcastU2U"] = (int)getFromCheckbutton("UserBroadcastU2U");
tmpl["BroadcastCrossChannel"] = (int)getFromCheckbutton("UserBroadcastxChan");
tmpl["SendTTS"] = (int)getFromCheckbutton("UserSendTTSBinds");
tmpl["SendWave"] = (int)getFromCheckbutton("UserSendWaveBinds");
tmpl["SendPages"] = (int)getFromCheckbutton("UserSendPages");
tmpl["SetPhonetic"] = (int)getFromCheckbutton("UserSetPhonetic");
tmpl["SendComments"] = (int)getFromCheckbutton("UserSendComment");
tmpl["CommentSounds"] = (int)getFromCheckbutton("UserGenCommentSounds");
tmpl["EventSounds"] = (int)getFromCheckbutton("UserEventSounds");
tmpl["MuteGlobally"] = (int)getFromCheckbutton("UserMuteGlobally");
tmpl["MuteOthersPTT"] = (int)getFromCheckbutton("UserMuteOthers");
tmpl["Chat"] = (int)getFromCheckbutton("UserGlobalChat");
tmpl["InitPrivateChat"] = (int)getFromCheckbutton("UserPrivateChat");
tmpl["Equalizer"] = (int)getFromCheckbutton("UserEqOut");
tmpl["SeeGuest"] = (int)getFromCheckbutton("UserSeeGuests");
tmpl["SeeNonGuest"] = (int)getFromCheckbutton("UserSeeNonGuests");
tmpl["SeeMotd"] = (int)getFromCheckbutton("UserSeeMOTD");
tmpl["SeeServerComment"] = (int)getFromCheckbutton("UserSeeServerComment");
tmpl["SeeChannels"] = (int)getFromCheckbutton("UserSeeChannelList");
tmpl["SeeChannelComments"] = (int)getFromCheckbutton("UserSeeChannelComments");
tmpl["SeeUserComments"] = (int)getFromCheckbutton("UserSeeUserComments");
tmpl["ServerAdmin"] = (int)getFromCheckbutton("UserServerAdmin");
tmpl["AddUsers"] = (int)getFromCheckbutton("UserAddUsers");
tmpl["DeleteUsers"] = (int)getFromCheckbutton("UserRemoveUsers");
tmpl["BanUsers"] = (int)getFromCheckbutton("UserBanUsers");
tmpl["KickUsers"] = (int)getFromCheckbutton("UserKickUsers");
tmpl["MoveUsers"] = (int)getFromCheckbutton("UserMoveUsers");
tmpl["EditChanAdmins"] = (int)getFromCheckbutton("UserAssignChanAdmin");
tmpl["EditRanks"] = (int)getFromCheckbutton("UserEditRanks");
tmpl["EditMotd"] = (int)getFromCheckbutton("UserEditMOTD");
tmpl["EditGuestMotd"] = (int)getFromCheckbutton("UserEditGuestMOTD");
tmpl["RCon"] = (int)getFromCheckbutton("UserIssueRcon");
tmpl["GroupEditVoice"] = (int)getFromCheckbutton("UserEditVoiceTargets");
tmpl["GroupEditCmd"] = (int)getFromCheckbutton("UserEditCommandTargets");
tmpl["RankAssign"] = (int)getFromCheckbutton("UserAssignRank");
tmpl["ReservedAssign"] = (int)getFromCheckbutton("UserAssignReserved");
tmplfile.save();
if (path) {
::free(path);
}
loadUserTemplates();
statusbarPush("Saved '" + name + "' template.");
}/*}}}*/
/* ---------- Rank Editor Related Methods ---------- */
Gtk::TreeModel::iterator
ManglerAdmin::getRank(uint16_t id, Gtk::TreeModel::Children children) {/*{{{*/
Gtk::TreeModel::iterator iter = children.begin();
while (iter != children.end()) {
if ((*iter)[rankRecord.id] == id) break;
iter++;
}
return iter;
}/*}}}*/
void
ManglerAdmin::rankUpdated(v3_rank *rank) {/*{{{*/
Gtk::TreeModel::iterator iter = getRank(rank->id, RankEditorModel->children());
if (! iter) iter = RankEditorModel->append();
(*iter)[rankRecord.id] = rank->id;
(*iter)[rankRecord.level] = rank->level;
(*iter)[rankRecord.name] = c_to_ustring(rank->name);
(*iter)[rankRecord.description] = c_to_ustring(rank->description);
queue_resize(RankEditorTree);
/* now handle the User Rank combo box */
/* the poorly named getAccount() will work fine for this */
Gtk::TreeModel::Row row = getAccount(rank->id, UserRankModel->children());
if (! row) row = *(UserRankModel->append());
row[adminRecord.id] = rank->id;
row[adminRecord.name] = c_to_ustring(rank->name);
/* update status bar */
statusbarPush(Glib::ustring::compose("Rank %1 (%2) updated.", Glib::ustring::format(rank->id), c_to_ustring(rank->name)));
}/*}}}*/
void
ManglerAdmin::rankAdded(v3_rank *rank) {/*{{{*/
Gtk::TreeModel::iterator iter = RankEditorModel->append();
(*iter)[rankRecord.id] = rank->id;
(*iter)[rankRecord.level] = rank->level;
(*iter)[rankRecord.name] = c_to_ustring(rank->name);
(*iter)[rankRecord.description] = rank->description;
if (currentRankID == 0xffff && c_to_ustring(rank->name) == trimString(getFromEntry("RankName"))) {
RankEditorTree->set_cursor(RankEditorModel->get_path(iter));
}
queue_resize(RankEditorTree);
/* now handle the User Rank combo box */
iter = UserRankModel->append();
(*iter)[adminRecord.id] = rank->id;
(*iter)[adminRecord.name] = c_to_ustring(rank->name);
/* update status bar */
statusbarPush(Glib::ustring::compose("Rank %1 (%2) added.", Glib::ustring::format(rank->id), c_to_ustring(rank->name)));
}/*}}}*/
void
ManglerAdmin::rankRemoved(uint16_t rankid) {/*{{{*/
Gtk::TreeModel::iterator iter = getRank(rankid, RankEditorModel->children());
if (iter) {
Gtk::TreeModel::Row rank = *iter;
iter = RankEditorTree->get_selection()->get_selected();
if (iter && (*iter)[rankRecord.id] == rank[rankRecord.id]) {
clearRankEditor();
}
RankEditorModel->erase(rank);
}
queue_resize(RankEditorTree);
/* now handle the User Rank combo box */
/* the poorly named getAccount() will work fine for this */
Gtk::TreeModel::Row row = getAccount(rankid, UserRankModel->children());
if (row) UserRankModel->erase(row);
/* update status bar */
statusbarPush(Glib::ustring::compose("Rank %1 removed.", Glib::ustring::format(rankid)));
}/*}}}*/
void
ManglerAdmin::rankRemoved(v3_rank *rank) {/*{{{*/
rankRemoved(rank->id);
}/*}}}*/
void
ManglerAdmin::RankUpdate_clicked_cb(void) {/*{{{*/
v3_rank rank;
rank.id = (currentRankID == 0xffff) ? 0 : currentRankID;
rank.name = ::strdup(ustring_to_c(getFromEntry("RankName")).c_str());
rank.description = ::strdup(ustring_to_c(getFromEntry("RankDescription")).c_str());
rank.level = uint16_t( getFromSpinbutton("RankLevel") );
v3_rank_update(&rank);
::free(rank.name);
::free(rank.description);
}/*}}}*/
void
ManglerAdmin::RankEditorTree_cursor_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = RankEditorTree->get_selection()->get_selected();
bool isRank( false );
if (iter) {
isRank = true;
currentRankID = (*iter)[rankRecord.id];
copyToEntry("RankName", (*iter)[rankRecord.name]);
copyToEntry("RankDescription", (*iter)[rankRecord.description]);
copyToSpinbutton("RankLevel", (*iter)[rankRecord.level]);
}
const v3_permissions *perms = v3_get_permissions();
bool editAccess( RankEditorOpen && perms->edit_rank );
setWidgetSensitive("RankAdd", editAccess);
setWidgetSensitive("RankRemove", editAccess && isRank);
setWidgetSensitive("RankUpdate", editAccess && isRank);
RankEditor->set_sensitive(isRank);
}/*}}}*/
void
ManglerAdmin::RankAdd_clicked_cb(void) {/*{{{*/
clearRankEditor();
currentRankID = 0xffff;
setWidgetSensitive("RankAdd", false);
setWidgetSensitive("RankUpdate", true);
RankEditor->set_sensitive(true);
}/*}}}*/
void
ManglerAdmin::RankRemove_clicked_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = RankEditorTree->get_selection()->get_selected();
if (! iter) return;
uint16_t rankid = (*iter)[rankRecord.id];
Glib::ustring rankname = (*iter)[rankRecord.name];
Gtk::MessageDialog confirmDlg( Glib::ustring::compose("Are you sure you want to remove rank %1 (%2)?", Glib::ustring::format(rankid), rankname), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true );
if (confirmDlg.run() == Gtk::RESPONSE_YES) {
v3_rank_remove(rankid);
}
}/*}}}*/
void
ManglerAdmin::clearRankEditor(void) {/*{{{*/
RankEditorTree->get_selection()->unselect_all();
RankEditor->set_sensitive(false);
copyToEntry("RankName", "");
copyToEntry("RankDescription", "");
copyToSpinbutton("RankLevel", 0);
setWidgetSensitive("RankAdd", RankEditorOpen);
setWidgetSensitive("RankRemove", false);
setWidgetSensitive("RankUpdate", RankEditorOpen);
currentRankID = 0;
}/*}}}*/
void
ManglerAdmin::clearRanks(void) {/*{{{*/
RankEditorModel->clear();
queue_resize(RankEditorTree);
clearRankEditor();
UserRankModel->clear();
Gtk::TreeModel::Row row = *(UserRankModel->append());
row[adminRecord.id] = 0;
row[adminRecord.name] = "(None)";
}/*}}}*/
/* ---------- Ban Editor Related Methods ---------- */
void
ManglerAdmin::banList(uint16_t id, uint16_t count, uint16_t bitmask_id, uint32_t ip_address, char *user, char *by, char *reason) {/*{{{*/
if (!id) {
BanEditorModel->clear();
queue_resize(BanEditorTree);
}
if (!count) {
clearBanEditor();
return;
}
Gtk::TreeModel::iterator iter = BanEditorModel->append();
(*iter)[banRecord.id] = id;
(*iter)[banRecord.ip_val] = ip_address;
(*iter)[banRecord.netmask_id] = bitmask_id;
(*iter)[banRecord.ip] = Glib::ustring::compose("%1.%2.%3.%4",
Glib::ustring::format((ip_address >> 24) & 0xff),
Glib::ustring::format((ip_address >> 16) & 0xff),
Glib::ustring::format((ip_address >> 8) & 0xff),
Glib::ustring::format(ip_address & 0xff));
(*iter)[banRecord.netmask] = c_to_ustring(_v3_bitmasks[bitmask_id]);
(*iter)[banRecord.user] = c_to_ustring(user);
(*iter)[banRecord.by] = c_to_ustring(by);
(*iter)[banRecord.reason] = c_to_ustring(reason);
if (ip_address == currentBanIP) {
BanEditorTree->set_cursor(BanEditorModel->get_path(iter));
}
queue_resize(BanEditorTree);
}/*}}}*/
void
ManglerAdmin::BanEditorTree_cursor_changed_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = BanEditorTree->get_selection()->get_selected();
bool isBan( false );
if (iter) {
isBan = true;
currentBanIP = (*iter)[banRecord.ip_val];
copyToEntry("BanIPAddress", (*iter)[banRecord.ip]);
copyToCombobox("BanNetmask", (*iter)[banRecord.netmask_id], BanNetmaskDefault);
copyToEntry("BanReason", (*iter)[banRecord.reason]);
}
setWidgetSensitive("BanAdd", true);
setWidgetSensitive("BanRemove", isBan);
BanEditor->set_sensitive(isBan);
}/*}}}*/
void
ManglerAdmin::BanAdd_clicked_cb(void) {/*{{{*/
clearBanEditor();
setWidgetSensitive("BanAdd", false);
BanEditor->set_sensitive(true);
}/*}}}*/
void
ManglerAdmin::BanRemove_clicked_cb(void) {/*{{{*/
Gtk::TreeModel::iterator iter = BanEditorTree->get_selection()->get_selected();
if (! iter) return;
uint32_t ip_address = (*iter)[banRecord.ip_val];
uint16_t bitmask_id = (*iter)[banRecord.netmask_id];
clearBanEditor();
v3_admin_ban_remove(bitmask_id, ip_address);
v3_admin_ban_list();
}/*}}}*/
void
ManglerAdmin::BanUpdate_clicked_cb(void) {/*{{{*/
uint32_t ip_address = 0;
char *ip_str = ::strdup(ustring_to_c(getFromEntry("BanIPAddress")).c_str());
uint16_t b1 = 0, b2 = 0, b3 = 0, b4 = 0;
if (::sscanf(ip_str, "%hu.%hu.%hu.%hu", &b1, &b2, &b3, &b4) != 4) {
::free(ip_str);
statusbarPush("Invalid IPv4 address.");
return;
}
::free(ip_str);
currentBanIP = ip_address =
((b1 << 24) & 0xff000000) |
((b2 << 16) & 0x00ff0000) |
((b3 << 8) & 0x0000ff00) |
((b4) & 0x000000ff);
uint16_t bitmask_id = getFromCombobox("BanNetmask", BanNetmaskDefault);
char *reason = ::strdup(ustring_to_c(getFromEntry("BanReason")).c_str());
v3_admin_ban_add(bitmask_id, ip_address, "Remotely added IP", reason);
::free(reason);
v3_admin_ban_list();
}/*}}}*/
void
ManglerAdmin::clearBanEditor(void) {/*{{{*/
BanEditorTree->get_selection()->unselect_all();
BanEditor->set_sensitive(false);
copyToEntry("BanIPAddress", "");
copyToCombobox("BanNetmask", BanNetmaskDefault);
copyToEntry("BanReason", "");
setWidgetSensitive("BanAdd", true);
setWidgetSensitive("BanRemove", false);
currentBanIP = -1;
}/*}}}*/
void
ManglerAdmin::clearBans(void) {/*{{{*/
BanEditorModel->clear();
queue_resize(BanEditorTree);
clearBanEditor();
}/*}}}*/
void
ManglerAdmin::clear(void) {/*{{{*/
adminNotebook->set_current_page(1);
setWidgetSensitive("ServerVBox", true);
SrvIsNotUpdating = true;
ChannelAdded = false;
SrvEditorOpen = false;
UserEditorOpen = false;
RankEditorOpen = false;
clearChannels();
clearUsers();
clearRanks();
clearBans();
}/*}}}*/
mangler-1.2.5/src/._mangleradmin.cpp 0000644 0000765 0000062 00000000336 11602153752 015262 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/mangler.ui 0000644 0000765 0000062 00001775577 12075416741 013727 0 ustar staff
Mangler - Server List
dialog
True
True
manglerWindow
True
5
5
True
Add
True
True
True
True
False
False
False
5
0
Remove
True
False
True
True
True
False
False
False
5
1
Clone
True
False
True
True
True
False
5
2
True
3
False
0
True
5
200
True
True
automatic
automatic
in
True
True
True
False
0
True
True
True
True
False
4
2
5
1
True
1
Server Name:
GTK_FILL
True
True
â—
True
1
2
True
1
Hostname/IP:
1
2
GTK_FILL
True
True
â—
True
1
2
1
2
True
1
Port:
2
3
GTK_FILL
True
True
5
â—
True
6
1
2
2
3
True
1
Default Channel:
3
4
GTK_FILL
True
True
â—
True
6
1
2
3
4
0
True
False
4
2
5
1
True
1
Password:
1
2
GTK_FILL
True
1
Username:
GTK_FILL
True
True
31
â—
True
1
2
True
True
31
False
â—
True
1
2
1
2
True
1
Phonetic:
2
3
GTK_FILL
True
True
31
â—
True
1
2
2
3
3
4
GTK_FILL
1
2
3
4
1
True
Server Configuration
False
True
True
False
5
4
2
10
Accept Page Requests
True
True
False
True
Accept Private Chat Requests
True
True
False
True
1
2
Accept User to User Transmissions
True
True
False
True
3
4
Allow Recording
True
True
False
True
2
3
Automatically reconnect
True
True
False
True
1
2
1
2
1
2
Restore previous channel on reconnect
True
False
True
1
2
2
3
True
5
True
Character Set:
False
0
1
True
1
1
2
3
4
1
True
Basic Options
1
False
False
1
True
5
True
0
Update
True
False
True
True
True
True
False
False
1
Close
True
True
True
False
False
2
False
2
1
5
center-on-parent
True
dialog
True
True
manglerWindow
Mangler
1.2.5
Copyright 2009-2011 by Eric Connell
http://www.mangler.org
http://www.mangler.org
Mangler 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 3 of the License, or (at your option) any later version.
Mangler 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 Mangler. If not, see <http://www.gnu.org/licenses>.
Eric Connell
Daniel Sloof
humbaba (anonymous)
Haxar (anonymous)
Felyza Wishbringer
Bob Shaffer II
Everyone else from Spux, without which
Mangler would not have been possible.
Specifically:
- Michael Sierks
- Cris Favero
And, of course, Luigi Auriemma
who figured out the encryption.
The source code is the documentation.
True
True
2
True
end
False
end
0
5
Mangler - Error Message
False
center-on-parent
True
dialog
True
True
True
manglerWindow
error
ok
True
2
True
end
False
end
0
5
Mangler - Quick Connect
True
center-on-parent
dialog
True
True
manglerWindow
True
2
True
4
2
5
1
True
1
Hostname/IP:
right
True
GTK_FILL
True
1
Port:
right
True
1
2
GTK_FILL
True
1
Username:
right
True
2
3
GTK_FILL
True
1
Password:
right
True
3
4
GTK_FILL
True
True
â—
True
1
2
True
True
â—
True
1
2
1
2
True
True
31
â—
True
1
2
2
3
True
True
31
False
â—
True
1
2
3
4
False
False
2
True
end
gtk-cancel
True
True
True
True
False
False
0
gtk-connect
True
True
True
True
False
False
1
False
end
0
qcCancelButton
qcConnectButton
Mangler - Settings
False
True
True
dialog
True
True
manglerWindow
True
True
True
True
5
5
5
5
True
Enable Keyboard Push to Talk
True
True
False
True
False
0
True
True
False
Push To Talk Key:
False
0
True
True
1
Set
75
True
False
True
True
False
2
False
2
1
True
False
6
2
Enable Mouse Button Push to Talk
True
True
False
True
False
3
True
5
True
False
Select Mouse:
False
0
True
False
1
False
2
4
True
True
False
Push To Talk Button:
False
0
True
True
1
Set
75
True
False
True
True
False
2
False
2
5
True
False
6
6
Enable "Now Playing" Music Player Integration
True
True
False
Show track information in your comment field which is currently playing in your media player software to other users in the channel list.
True
False
7
True
5
True
False
Media Player:
False
0
True
False
1
False
2
8
True
False
6
9
Enable Voice Activation
True
True
False
Specify the threshold in percentage to activate transmit and the duration of silence in seconds to deactivate transmit.
True
False
10
True
False
6
5
True
1
Silence Duration:
True
True
â—
settingsVoiceActivationSilenceDurationSpinButtonAdjustment
0.5
2
True
1
2
GTK_FILL
True
2.2351741291171123e-10
seconds
2
3
True
1
Sensitivity:
3
4
GTK_FILL
True
True
â—
settingsVoiceActivationSensitivitySpinButtonAdjustment
1
True
4
5
GTK_FILL
True
0
%
5
6
False
2
11
True
False
True
False
6
0
Enable On-Screen Display
True
True
False
Display various status information in plain text overlaid on your screen.
True
False
1
True
False
9
5
True
1
Vertical:
True
1
2
GTK_FILL
True
3
4
GTK_FILL
True
1
Size:
6
7
True
True
True
#0000ffff0000
5
6
True
1
Horizontal:
2
3
True
True
â—
settingsOSDfontsizeAdjustment
1
True
True
7
8
GTK_FILL
True
0
pt
8
9
True
1
Color:
4
5
False
2
2
False
12
True
General
False
True
5
13
2
5
5
True
1
Output Device:
3
4
GTK_FILL
GTK_FILL
True
1
2
3
4
GTK_FILL
True
1
Notification Device:
10
11
GTK_FILL
GTK_FILL
True
1
2
10
11
GTK_FILL
True
0
<b>Notifications</b>
Notifications are the sound effects which are played when you login, logout, a user joins your channel, etc.
True
True
word-char
2
9
10
GTK_FILL
True
2
8
9
GTK_FILL
5
True
2
2
Login and Logout
True
True
False
True
User Joins/Leaves Channel
True
True
False
True
1
2
Start and Stop Transmit
True
True
False
True
1
2
Text to Speech with Pages
True
False
True
False
True
1
2
1
2
2
12
13
True
True
0
<b>Master Volume</b>
True
False
0
2
6
7
GTK_FILL
True
2
5
6
GTK_FILL
5
True
1
Audio Subsystem:
GTK_FILL
GTK_FILL
True
1
2
GTK_FILL
True
True
User defined PCM device from .asoundrc or asound.conf
â—
1
2
4
5
GTK_FILL
True
True
User defined PCM device from .asoundrc or asound.conf
â—
1
2
11
12
GTK_FILL
True
1
Custom Output Device:
4
5
GTK_FILL
GTK_FILL
True
1
Custom Notification Device:
11
12
GTK_FILL
GTK_FILL
True
1
Custom Input Device:
2
3
GTK_FILL
GTK_FILL
True
True
User defined PCM device from .asoundrc or asound.conf
â—
1
2
2
3
GTK_FILL
True
1
2
1
2
GTK_FILL
True
1
Input Device:
1
2
GTK_FILL
GTK_FILL
True
True
0
<b>Input Gain</b>
True
False
0
2
7
8
GTK_FILL
1
True
Audio
1
False
True
5
5
5
5
True
True
0
True
9
2
Network Status Events
True
True
False
True
2
3
Error Messages
True
True
False
True
3
4
Packet Dumps
True
True
False
True
6
7
Internal Network Info
True
True
False
True
5
6
Stack Info
True
True
False
True
4
5
Packet Parsing
True
True
False
True
7
8
Socket Messages
True
True
False
True
1
2
2
3
General Notices
True
True
False
True
1
2
3
4
General Info
True
True
False
True
1
2
4
5
Mutex Info
True
True
False
True
1
2
5
6
Memory Allocation
True
True
False
True
1
2
6
7
Encrypted Packet Dumps
True
True
False
True
1
2
7
8
Event Queue
True
True
False
True
8
9
True
0
1
<span weight="bold">WARNING:</span> Enabling these debug settings can generate a substantial amount of output and resources.
These are useful for developers.
True
True
word-char
2
3
4
True
2
1
2
3
True
<b>Debug Output</b>
True
False
0
True
1
2
True
Debug
2
False
2
0
True
True
0
True
2
_Cancel
True
True
True
True
False
False
0
_Apply
True
True
True
True
False
False
1
_OK
True
True
True
True
False
False
2
False
1
False
1
5
Password
True
center-on-parent
True
dialog
True
True
manglerWindow
True
2
True
5
True
Password:
False
0
True
True
True
31
False
â—
True
1
False
1
True
end
gtk-cancel
True
True
True
True
False
False
False
0
gtk-ok
True
True
True
True
True
True
False
False
False
1
False
end
0
passwordCancelButton
passwordOkButton
10
Mangler - Message of the Day
center-on-parent
375
350
dialog
True
True
manglerWindow
True
10
True
False
True
False
automatic
automatic
in
True
True
False
2
2
False
True
Users
False
True
False
automatic
automatic
in
True
True
False
2
2
False
1
True
Guests
1
False
0
True
True
Ignore MOTD
True
False
False
False
True
False
0
0
gtk-ok
75
True
True
True
True
True
True
False
1
False
1
300
Mangler - User Settings
True
dialog
manglerWindow
True
5
5
5
5
True
True
True
0.05000000074505806
Username:
False
5
0
True
0.05000000074505806
label
1
False
5
0
True
False
1
True
True
True
4
User Volume
False
0
True
True
True
0
left
1
False
0
True
False
False
5
1
True
True
never
automatic
True
queue
none
250
True
5
True
10
2
4
True
1
Accepts Private Voice Chat:
GTK_FILL
True
No
1
2
GTK_FILL
True
1
Allows Recording:
1
2
GTK_FILL
True
No
1
2
1
2
GTK_FILL
True
1
Accepts Pages:
2
3
GTK_FILL
True
No
1
2
2
3
GTK_FILL
True
1
Accepts Private Text Chat:
3
4
GTK_FILL
True
No
1
2
3
4
GTK_FILL
2
4
5
GTK_FILL
True
2
5
6
GTK_FILL
True
0
<b>URL</b>
True
2
7
8
GTK_FILL
True
2
8
9
GTK_FILL
True
True
automatic
never
True
queue
none
2
6
7
GTK_FILL
True
True
automatic
never
True
queue
none
URL Text
True
True
True
none
False
0.05000000074505806
http://www.mangler.org
2
9
10
GTK_FILL
2
2
5
Mangler - Change Text
center-on-parent
dialog
True
True
manglerWindow
True
2
True
3
2
5
2
GTK_FILL
GTK_FILL
2
True
1
URL:
1
2
GTK_FILL
GTK_FILL
2
1
Integration (music):
2
3
GTK_FILL
GTK_FILL
2
1
2
GTK_FILL
True
True
127
â—
True
1
2
1
2
GTK_FILL
True
127
â—
True
1
2
2
3
GTK_FILL
False
1
False
False
2
2
True
True
end
gtk-cancel
True
True
True
True
False
False
0
gtk-ok
True
True
True
True
True
True
False
False
1
False
end
0
textStringCancelButton
textStringOkButton
Mangler - Chat
500
300
True
3
3
3
3
True
True
375
True
True
False
automatic
automatic
in
True
False
word-char
2
2
False
True
True
True
False
automatic
automatic
in
True
False
False
False
True
0
True
Timestamp
True
True
False
False
True
False
0
False
1
True
2
True
True
True
True
True
True
True
255
â—
True
0
Clear
True
True
True
False
False
1
Close
True
True
True
False
False
2
Hide
True
True
True
False
False
3
False
2
True
gtk-edit
16
True
gtk-dialog-question
True
gtk-properties
5
Mangler - Reason
True
center-on-parent
True
dialog
True
True
manglerWindow
True
2
True
5
True
Reason:
False
0
True
True
127
â—
True
1
False
1
True
end
gtk-cancel
True
True
True
True
False
False
False
0
gtk-ok
True
True
True
True
True
True
False
False
False
1
False
end
0
reasonCancelButton
reasonOkButton
5
Mangler - Admin Window
640
480
True
5
True
True
True
True
5
True
4
True
True
automatic
automatic
True
queue
True
5
29
2
5
2
GTK_FILL
1
2
GTK_FILL
True
1
Max Guests:
6
7
GTK_FILL
True
1
Kick Guests after:
7
8
GTK_FILL
True
1
Ban Guests for:
8
9
GTK_FILL
True
True
True
â—
adminServerKickGuestsAdjustment
True
0
True
minutes
False
5
1
1
2
7
8
GTK_FILL
True
True
True
â—
adminServerBanGuestsAdjustment
True
0
True
minutes
False
5
1
1
2
8
9
GTK_FILL
True
2
5
6
GTK_FILL
True
0.05000000074505806
3
<b>Guest Accounts</b>
True
2
4
5
GTK_FILL
True
0.05000000074505806
3
<b>Inactivity</b>
True
2
9
10
GTK_FILL
True
2
10
11
GTK_FILL
True
1
Timeout:
11
12
GTK_FILL
True
True
True
â—
adminServerTimeoutAdjustment
True
0
True
minutes
False
5
1
1
2
11
12
GTK_FILL
True
1
Action:
12
13
GTK_FILL
True
1
2
13
14
GTK_FILL
True
1
2
12
13
GTK_FILL
True
1
Channel:
13
14
GTK_FILL
True
1
Chat Filter:
1
2
GTK_FILL
True
1
Channel Ordering:
2
3
GTK_FILL
True
1
2
1
2
GTK_FILL
True
1
2
2
3
GTK_FILL
Always Display MOTD
True
True
False
True
2
3
4
GTK_FILL
True
0.05000000074505806
3
<b>Spam Filters</b>
True
2
14
15
GTK_FILL
True
2
15
16
GTK_FILL
True
6
4
5
2
True
1
Channel:
1
2
GTK_FILL
True
1
Chat:
2
3
GTK_FILL
3
4
GTK_FILL
True
1
Text To Speech Bind:
4
5
GTK_FILL
True
1
Wave Bind:
5
6
GTK_FILL
True
True
<b>Action</b>
True
0
True
False
1
1
2
True
True
<b>Interval</b>
True
0
True
False
1
2
3
True
<b>Times</b>
True
3
4
True
1
2
1
2
True
1
2
2
3
1
2
3
4
True
1
2
4
5
True
1
2
5
6
True
True
â—
adminServerSpamFilterChannelIntervalAdjustment
True
2
3
1
2
True
True
â—
adminServerSpamFilterChatIntervalAdjustment
True
2
3
2
3
2
3
3
4
True
True
â—
adminServerSpamFilterTTSIntervalAdjustment
True
2
3
4
5
True
True
â—
adminServerSpamFilterWaveIntervalAdjustment
True
2
3
5
6
True
True
â—
adminServerSpamFilterChannelTimesAdjustment
True
3
4
1
2
True
True
â—
adminServerSpamFilterChatTimesAdjustment
True
3
4
2
3
3
4
3
4
True
True
â—
adminServerSpamFilterTTSTimesAdjustment
True
3
4
4
5
True
True
â—
adminServerSpamFilterWaveTimesAdjustment
True
3
4
5
6
2
16
17
True
0.05000000074505806
3
<b>Bind Filters</b>
True
2
17
18
GTK_FILL
True
2
18
19
GTK_FILL
Disable Text To Speech Binds
True
True
False
True
2
19
20
GTK_FILL
Disable Wave Binds
True
True
False
True
2
20
21
GTK_FILL
True
0.05000000074505806
3
<b>Remote Status</b>
True
2
21
22
GTK_FILL
True
2
22
23
GTK_FILL
2
23
24
GTK_FILL
Return Channel Names
True
True
False
True
2
24
25
GTK_FILL
2
25
26
GTK_FILL
Return User Names
True
True
False
True
2
26
27
GTK_FILL
2
27
28
GTK_FILL
Kick logins who don't show their user name for remote status requests.
True
True
False
True
2
28
29
GTK_FILL
True
True
â—
adminServerMaxGuestsAdjustment
True
1
2
6
7
0
Update
True
True
True
False
1
True
Server
False
True
5
True
True
175
True
True
True
True
automatic
automatic
in
True
True
False
True
0
Add
True
True
True
False
5
1
Remove
True
True
True
False
2
True
True
True
True
0.05000000074505806
Editing: NONE
False
2
0
True
True
never
automatic
True
queue
True
5
True
14
2
5
2
True
1
Name:
GTK_FILL
True
1
Phonetic:
1
2
GTK_FILL
2
3
GTK_FILL
True
1
Password:
3
4
GTK_FILL
True
True
31
False
â—
1
2
3
4
1
2
2
3
True
True
31
â—
1
2
1
2
True
True
31
â—
1
2
True
1
Protected Mode:
4
5
GTK_FILL
True
1
Voice Mode:
5
6
GTK_FILL
True
1
2
4
5
True
1
2
5
6
True
1
Codec:
7
8
GTK_FILL
True
1
2
7
8
True
1
Format:
8
9
GTK_FILL
True
1
2
8
9
True
2
6
7
4
True
2
9
10
4
True
1
Transmit Time Limit:
10
11
GTK_FILL
True
1
Transmit Rank Level:
11
12
GTK_FILL
True
1
Max Clients:
12
13
GTK_FILL
True
3
2
5
2
True
True
â—
adminTransmitTimeLimitAdjustment
1
True
True
True
seconds
1
2
GTK_FILL
True
True
â—
adminTransmitRankLevelAdjustment
1
True
True
1
2
True
0 to 100
1
2
1
2
GTK_FILL
True
True
â—
adminMaxClientsAdjustment
1
True
True
2
3
True
0 to N
1
2
2
3
GTK_FILL
1
2
10
13
True
2
13
14
4
0
Allow Recording
True
True
False
True
1
Allow Cross Channel Transmitting
True
True
False
True
2
Allow Paging
True
True
False
True
3
Allow Wave File Binds
True
True
False
True
4
Allow TTS Binds
True
True
False
True
5
Allow User to User Transmitting
True
True
False
True
6
Allow Phantoms
True
True
False
True
7
Allow Guests to Join
True
True
False
True
8
Allow Voice Targets
True
True
False
True
9
Allow Commanding Targets
True
True
False
True
10
Exempt from Inactivity Timers
True
True
False
True
11
Mute Guests
True
True
False
True
12
Disable Sound Events
True
True
False
True
13
4
1
Update
True
True
True
False
2
True
True
1
True
Channels
1
False
True
5
True
True
175
True
True
True
True
automatic
automatic
in
True
True
False
0
Add
True
True
True
False
5
1
Remove
True
True
True
False
2
True
True
True
False
True
0.05000000074505806
Editing: NONE
False
False
2
0
True
5
True
Template:
False
0
1
True
1
Load
True
True
True
False
2
Delete
True
True
True
False
3
True
False
4
Save...
True
True
True
False
5
False
False
3
1
True
True
never
automatic
True
queue
True
5
Info
True
True
True
UserInfoArrow
0
False
False
0
5
2
5
2
True
1
Login:
GTK_FILL
True
1
Password:
1
2
GTK_FILL
True
1
Owner:
2
3
GTK_FILL
True
True
31
â—
1
2
True
True
31
False
â—
1
2
1
2
True
1
Notes:
4
5
GTK_FILL
True
1
Rank:
3
4
GTK_FILL
True
1
2
3
4
GTK_FILL
True
1
2
2
3
GTK_FILL
90
True
True
automatic
automatic
in
True
True
2
2
2
1
2
4
5
False
False
4
1
True
False
4
2
Network
True
True
True
UserNetworkArrow
0
False
False
3
Account Locked
True
True
False
True
0
True
5
True
Reason:
False
0
True
True
127
â—
1
2
1
In Reserved List
True
True
False
True
2
Receive Broadcast Streams
True
True
False
True
3
Add Phantoms
True
True
False
True
4
Allow Record
True
True
False
True
5
Ignore Inactivity Timers
True
True
False
True
6
Send Complaints
True
True
False
True
7
Receive Complaints
True
True
False
True
8
True
5
True
Duplicate IPs:
False
0
True
1
False
False
2
9
Switch Channels
True
True
False
True
10
True
5
True
Default Channel:
False
0
True
1
False
False
2
11
False
False
4
4
True
False
4
5
Transmit
True
True
True
UserTransmitArrow
0
False
False
6
Broadcast
True
True
False
True
0
Broadcast to Lobby
True
True
False
True
1
Broadcast User to User
True
True
False
True
2
Broadcast Cross Channel
True
True
False
True
3
Send TTS Binds
True
True
False
True
4
Send Wave File Binds
True
True
False
True
5
Send Pages
True
True
False
True
6
Set Phonetic Name
True
True
False
True
7
8
9
Event Sounds
True
True
False
True
10
Mute Globally at Login
True
True
False
True
11
Mute Others While Talking
True
True
False
True
12
Use Global Chat
True
True
False
True
13
Initiate Private Chat
True
True
False
True
14
Use Outbound Equalizer
True
True
False
True
15
False
False
4
7
True
False
4
8
Display
True
True
True
UserDisplayArrow
0
False
False
9
See Guest Accounts
True
True
False
True
0
See Non Guest Accounts
True
True
False
True
1
See MOTD
True
True
False
True
2
3
See Channel List
True
True
False
True
4
5
6
False
False
4
10
True
False
4
11
Admin
True
True
True
UserAdminArrow
0
False
False
12
Server Admin
True
True
False
True
0
Add Users
True
True
False
True
1
Remove Users
True
True
False
True
2
Ban Users
True
True
False
True
3
Kick Users
True
True
False
True
4
Move Users
True
True
False
True
5
Assign/Edit Channel Admin/Authorization
True
True
False
True
6
Assign Rank
True
True
False
True
7
Edit Ranks
True
True
False
True
8
Edit MOTD
True
True
False
True
9
Edit Guest MOTD
True
True
False
True
10
Issue Rcon Commands
True
True
False
True
11
Edit Voice Targets
True
True
False
True
12
Edit Commanding Targets
True
True
False
True
13
Assign Reserved
True
True
False
True
14
False
False
4
13
True
False
4
14
Channel Admin
True
True
True
UserChanAdminArrow
0
False
False
15
True
False
False
4
16
True
False
4
17
Channel Authorization
True
True
True
UserChanAuthArrow
0
False
False
18
True
False
False
4
19
True
False
4
20
4
2
Update
True
True
True
False
3
True
True
2
True
Users
2
False
True
5
True
5
True
Add
True
True
True
False
False
5
0
Remove
True
True
True
False
False
5
1
True
2
False
0
True
True
True
automatic
automatic
in
True
True
False
0
True
True
3
2
5
2
True
1
Name:
GTK_FILL
True
1
Level:
1
2
GTK_FILL
True
True
15
â—
1
2
True
True
63
â—
1
2
2
3
True
True
â—
adminRankLevelAdjustment
1
True
True
1
2
1
2
True
1
Description:
2
3
GTK_FILL
False
4
0
Update
True
True
True
1
False
1
1
3
True
Ranks
3
False
True
5
5
True
Add
True
True
True
False
False
5
0
Remove
True
True
True
False
False
5
1
True
2
False
0
True
True
True
automatic
automatic
in
True
True
False
0
True
True
3
2
5
2
True
1
IP Address:
GTK_FILL
True
1
Netmask:
1
2
GTK_FILL
True
True
â—
1
2
True
True
127
â—
1
2
2
3
True
1
Reason:
2
3
GTK_FILL
True
1
2
1
2
False
4
0
Update
True
True
True
1
False
1
1
4
True
Bans
4
False
0
True
5
True
queue
True
2
False
0
Close
True
True
True
False
False
1
False
1
Mangler - Private Chat
500
300
True
3
3
3
3
True
3
True
False
automatic
automatic
in
True
True
False
word-char
2
2
False
0
True
2
True
True
True
True
255
â—
True
0
Send
True
False
True
True
True
False
False
1
Close
True
True
True
False
False
2
False
1
5
Mangler - Error Message
False
True
dialog
True
True
True
manglerWindow
True
True
True
True
20
20
8
True
0
0
gtk-dialog-error
6
False
0
True
1
False
0
True
10
10
10
10
True
0.05000000074505806
0.05000000074505806
Error Message
True
word-char
1
0
True
True
0
gtk-ok
100
True
True
True
True
True
True
False
1
False
1
True
gtk-preferences
True
gtk-dialog-authentication
True
gtk-dialog-authentication
True
gtk-connect
300
0.5
1
100
1
10
65535
1
10
100
1
10
65535
1
10
8
8
30
0.5
1
100
1
10
Mangler - Recorder
275
415
True
False
0
True
True
False
True
2
4
True
4
True
True
False
â—
0
Open...
True
True
True
False
False
1
False
0
True
0
0.10000000149011612
in
True
2
2
True
False
5
4
5
True
True
1
Type:
GTK_FILL
True
1
Size:
2
3
GTK_FILL
True
1
Count:
1
2
GTK_FILL
True
1
Duration:
2
3
1
2
GTK_FILL
True
1
Platform:
2
3
GTK_FILL
True
1
Version:
2
3
2
3
GTK_FILL
True
1
Codec:
4
5
GTK_FILL
True
0
N/A
1
2
GTK_FILL
True
0
N/A
3
4
GTK_FILL
True
0
N/A
1
2
1
2
GTK_FILL
True
0
N/A
end
3
4
1
2
GTK_FILL
True
0
N/A
end
1
2
2
3
GTK_FILL
True
0
N/A
end
3
4
2
3
GTK_FILL
True
0
N/A
1
4
4
5
GTK_FILL
True
4
3
4
4
False
1
True
True
automatic
automatic
in
True
False
True
False
2
True
0
0.10000000149011612
in
True
True
5
5
gtk-media-play
True
False
True
True
True
0
gtk-media-stop
True
False
True
True
True
False
1
True
False
2
gtk-media-record
True
False
True
True
True
False
3
True
False
4
_Info...
True
False
True
True
True
False
5
False
3
True
False
2
1
5
Mangler - Recording Info
normal
True
2
True
5
True
5
True
Recorded by:
False
0
True
True
127
â—
1
False
0
1
True
0
in
True
2
12
True
True
automatic
automatic
in
True
True
2
2
False
True
URL
True
2
True
0
in
True
2
12
True
True
automatic
automatic
in
True
True
2
2
False
True
Copyright
True
3
1
True
end
gtk-cancel
True
True
True
True
False
False
0
gtk-save
True
True
True
True
True
True
False
False
1
False
end
0
recInfoCancel
recInfoSave
True
gtk-properties
65535
1
10
65535
1
10
65535
1
10
65535
1
10
1000
500
60000
50
500
1000
500
60000
50
500
1000
500
60000
50
500
1000
500
60000
50
500
2
1
4
1
1
2
1
4
1
1
2
1
4
1
1
2
1
4
1
1
True
True
True
True
True
True
True
mangler-1.2.5/src/._mangler.ui 0000644 0000765 0000062 00000000336 12075416741 014111 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/mangler.h 0000644 0000765 0000062 00000025332 11602153752 013504 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/mangler.h $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include "config.h"
#include
#include
#include
#include
#include
#include "manglerconfig.h"
class ManglerChannelTree;
class ManglerNetwork;
class ManglerAudio;
class ManglerSettings;
class ManglerServerList;
class ManglerChat;
class ManglerPrivChat;
class ManglerIntegration;
class ManglerAdmin;
class ManglerRecorder;
#ifdef HAVE_XOSD
class ManglerOsd;
#endif
#ifdef HAVE_G15
class ManglerG15;
#endif
extern "C" {
#include
}
#ifndef _MANGLER_H
#define _MANGLER_H
struct _cli_options {
bool uifromfile;
Glib::ustring uifilename;
Glib::ustring qc_server;
Glib::ustring qc_username;
Glib::ustring qc_password;
};
class Mangler
{
public:
Mangler(struct _cli_options *options);
~Mangler();
void onDisconnectHandler(void);
void startTransmit(void);
void stopTransmit(void);
void initialize(void);
Gtk::Window *manglerWindow;
Glib::RefPtr builder;
Gtk::Button *button;
Gtk::ToggleButton *togglebutton;
Gtk::Dialog *dialog;
Gtk::AboutDialog *aboutdialog;
Gtk::MessageDialog *msgdialog;
Gtk::Window *window;
Gtk::ProgressBar *progressbar;
Gtk::Statusbar *statusbar;
Gtk::Label *label;
Gtk::Entry *entry;
Gtk::ComboBox *combobox;
Gtk::TextView *textview;
Gtk::VBox *vbox;
Gtk::CheckMenuItem *checkmenuitem;
Gtk::MenuItem *menuitem;
Gtk::Table *table;
Gtk::CheckButton *checkbutton;
Gtk::ProgressBar *inputvumeter;
std::map > icons;
Glib::RefPtr statusIcon;
Gtk::Menu *statusIconMenu;
ManglerServerList *serverList;
ManglerChat *chat;
ManglerChannelTree *channelTree;
ManglerNetwork *network;
//int32_t connectedServerId;
std::string connectedServerName;
std::map outputAudio;
std::map privateChatWindows;
ManglerAudio *inputAudio;
ManglerAudio *audioControl;
ManglerSettings *settings;
ManglerIntegration *integration;
ManglerAdmin *admin;
ManglerRecorder *recorder;
static ManglerConfig config;
#ifdef HAVE_XOSD
ManglerOsd *osd;
#endif
#ifdef HAVE_G15
ManglerG15 *g15;
#endif
bool isTransmitting;
bool isTransmittingButton;
bool isTransmittingVA;
bool isTransmittingKey;
bool isTransmittingMouse;
bool iconified;
bool isAdmin;
bool isChanAdmin;
bool muteSound;
bool muteMic;
bool motdAlways;
bool wantAdminWindow;
int espeakRate;
Glib::ustring CurrentOpenMouse;
XDevice *dev; // the currently open mouse device pointer
// Autoreconnect feature stuff - Need ID's to kill threads if needed
bool wantDisconnect;
time_t lastAttempt;
uint32_t lastServer;
// These are used by the message of the day window
Gtk::Window *motdWindow;
Gtk::Notebook *motdNotebook;
Gtk::TextView *motdUsers;
Gtk::TextView *motdGuests;
Gtk::CheckButton *motdIgnore;
Gtk::Button *motdOkButton;
// These are used by the password entry dialog
Gtk::Dialog *passwordDialog;
Gtk::Entry *passwordEntry;
Glib::ustring password;
bool passwordStatus;
// These are used by the kick/ban reason entry dialog
Gtk::Dialog *reasonDialog;
Gtk::Entry *reasonEntry;
Glib::ustring reason;
bool reasonStatus;
bool reasonValid;
// These are used by the text string entry dialog
Gtk::Dialog *textStringChangeDialog;
Gtk::Entry *textStringChangeCommentEntry;
Gtk::Entry *textStringChangeURLEntry;
Gtk::Entry *textStringChangeIntegrationEntry;
Gtk::CheckButton *textStringSilenceCommentCheckButton;
Glib::ustring comment;
Glib::ustring url;
Glib::ustring integration_text;
//Glib::Thread *networkThread;
Glib::ustring getPasswordEntry(Glib::ustring title = "Password", Glib::ustring prompt = "Password");
bool getReasonEntry(Glib::ustring title = "Reason", Glib::ustring prompt = "Reason");
uint32_t getActiveServer(void);
void setActiveServer(uint32_t row_number);
void errorDialog(Glib::ustring message);
void setTooltip(void);
std::string stripMotdRtf(const char *input);
protected:
struct _cli_options *options;
// main window callbacks
void mangler_show_cb(void);
bool mangler_quit_cb(void);
// connection handlers
void onConnectHandler(
Glib::ustring hostname,
Glib::ustring port,
Glib::ustring username,
Glib::ustring password,
Glib::ustring phonetic = "",
Glib::ustring charset = "",
bool acceptPages = true,
bool acceptU2U = true,
bool acceptPrivateChat = true,
bool allowRecording = true);
bool reconnectStatusHandler(void);
// button signal handlers
void quickConnectButton_clicked_cb(void);
void serverListButton_clicked_cb(void);
void connectButton_clicked_cb(void);
void commentButton_clicked_cb(void);
void chatButton_clicked_cb(void);
void bindingsButton_clicked_cb(void);
void adminButton_clicked_cb(void);
void settingsButton_clicked_cb(void);
void aboutButton_clicked_cb(void);
void xmitButton_toggled_cb(void);
void statusIcon_activate_cb(void);
void statusIcon_scroll_event_cb(GdkEventScroll* event);
void statusIcon_buttonpress_event_cb(GdkEventButton* event);
void errorOKButton_clicked_cb(void);
// menu bar signal handlers
void buttonMenuItem_toggled_cb(void);
void hideServerInfoMenuItem_toggled_cb(void);
void hideGuestFlagMenuItem_toggled_cb(void);
void motdMenuItem_activate_cb(void);
void recorderMenuItem_activate_cb(void);
void quitMenuItem_activate_cb(void);
void adminLoginMenuItem_activate_cb(void);
void adminWindowMenuItem_activate_cb(void);
bool getNetworkEvent(void);
bool updateIntegration(void); // music player integration
bool checkPushToTalkKeys(void);
bool checkVoiceActivation(void);
bool checkPushToTalkMouse(void);
bool updateXferAmounts(void);
// quick mute options
void muteSoundCheckButton_toggled_cb(void);
void muteMicCheckButton_toggled_cb(void);
void muteSoundCheckMenuItem_toggled_cb(void);
void muteMicCheckMenuItem_toggled_cb(void);
// quick connect signal handlers
void qcConnectButton_clicked_cb(void);
void qcCancelButton_clicked_cb(void);
// message of the day window signal handlers
void motdIgnore_toggled_cb(void);
void motdOkButton_clicked_cb(void);
// password dialog signal handlers
void passwordDialogOkButton_clicked_cb(void);
void passwordDialogCancelButton_clicked_cb(void);
// kick/ban reason dialog signal handlers
void reasonDialogOkButton_clicked_cb(void);
void reasonDialogCancelButton_clicked_cb(void);
// text string change dialog signal handlers
void textStringChangeDialogOkButton_clicked_cb(void);
void textStringChangeDialogCancelButton_clicked_cb(void);
};
class ManglerError
{
public:
uint32_t code;
Glib::ustring message;
Glib::ustring module;
ManglerError(uint32_t code, Glib::ustring message, Glib::ustring module = "");
};
GdkFilterReturn ptt_filter(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data);
extern Mangler *mangler;
#endif
mangler-1.2.5/src/._mangler.h 0000644 0000765 0000062 00000000336 11602153752 013716 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/mangler.cpp 0000644 0000765 0000062 00000277674 11602153752 014061 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/mangler.cpp $
*
* Copyright 2009-2011 Eric Connell
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#include
#include
#include
#include
#include
#include "mangler.h"
#include "manglerui.h"
#include "mangler-icons.h"
#include "channeltree.h"
#include "manglernetwork.h"
#include "mangleraudio.h"
#include "manglersettings.h"
#include "manglerserverlist.h"
#include "manglerchat.h"
#include "manglerprivchat.h"
#include "manglercharset.h"
#include "manglerintegration.h"
#include "mangleradmin.h"
#include "manglerrecorder.h"
#ifdef HAVE_XOSD
# include "manglerosd.h"
#endif
#ifdef HAVE_G15
# include "manglerg15.h"
#endif
#include "locale.h"
using namespace std;
Mangler *mangler;
ManglerConfig Mangler::config;
Mangler::Mangler(struct _cli_options *options) {/*{{{*/
this->options = options;
// load all of our icons
icons.insert(std::make_pair("black_circle", Gdk::Pixbuf::create_from_inline(-1, black_circle )));
icons.insert(std::make_pair("blue_circle", Gdk::Pixbuf::create_from_inline(-1, blue_circle )));
icons.insert(std::make_pair("cyan_circle", Gdk::Pixbuf::create_from_inline(-1, cyan_circle )));
icons.insert(std::make_pair("green_circle", Gdk::Pixbuf::create_from_inline(-1, green_circle )));
icons.insert(std::make_pair("purple_circle", Gdk::Pixbuf::create_from_inline(-1, purple_circle )));
icons.insert(std::make_pair("red_circle", Gdk::Pixbuf::create_from_inline(-1, red_circle )));
icons.insert(std::make_pair("yellow_circle", Gdk::Pixbuf::create_from_inline(-1, yellow_circle )));
icons.insert(std::make_pair("mangler_logo", Gdk::Pixbuf::create_from_inline(-1, mangler_logo )));
icons.insert(std::make_pair("tray_icon", Gdk::Pixbuf::create_from_inline(-1, tray_icon_purple )));
icons.insert(std::make_pair("tray_icon_blue", Gdk::Pixbuf::create_from_inline(-1, tray_icon_blue )));
icons.insert(std::make_pair("tray_icon_red", Gdk::Pixbuf::create_from_inline(-1, tray_icon_red )));
icons.insert(std::make_pair("tray_icon_green", Gdk::Pixbuf::create_from_inline(-1, tray_icon_green )));
icons.insert(std::make_pair("tray_icon_yellow", Gdk::Pixbuf::create_from_inline(-1, tray_icon_yellow )));
icons.insert(std::make_pair("tray_icon_grey", Gdk::Pixbuf::create_from_inline(-1, tray_icon_grey )));
icons.insert(std::make_pair("tray_icon_purple", Gdk::Pixbuf::create_from_inline(-1, tray_icon_purple )));
icons.insert(std::make_pair("user_icon_red", Gdk::Pixbuf::create_from_inline(-1, user_icon_red )));
icons.insert(std::make_pair("user_icon_yellow", Gdk::Pixbuf::create_from_inline(-1, user_icon_yellow )));
icons.insert(std::make_pair("user_icon_green", Gdk::Pixbuf::create_from_inline(-1, user_icon_green )));
icons.insert(std::make_pair("user_icon_orange", Gdk::Pixbuf::create_from_inline(-1, user_icon_orange )));
try {
if (options->uifromfile) {
builder = Gtk::Builder::create_from_file(options->uifilename);
} else {
builder = Gtk::Builder::create_from_string(ManglerUI);
}
builder->get_widget("manglerWindow", manglerWindow);
manglerWindow->set_icon(icons["tray_icon"]);
} catch (const Glib::Error& e) {
std::cerr << e.what() << std::endl;
exit(EXIT_FAILURE);
}
manglerWindow->signal_show().connect(sigc::mem_fun(this, &Mangler::mangler_show_cb));
//manglerWindow->signal_hide().connect(sigc::mem_fun(this, &Mangler::manglerWindow_hide_cb));
Gtk::Main::signal_quit().connect(sigc::mem_fun(this, &Mangler::mangler_quit_cb));
/*
* Retreive all buttons from builder and set their singal handler callbacks
*/
// Quick Connect Button
builder->get_widget("quickConnectButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::quickConnectButton_clicked_cb));
// Server List Button
builder->get_widget("serverListButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::serverListButton_clicked_cb));
// Connect Button
builder->get_widget("connectButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::connectButton_clicked_cb));
// Comment Button
builder->get_widget("commentButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::commentButton_clicked_cb));
// Chat Button
builder->get_widget("chatButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::chatButton_clicked_cb));
// Bindings Button
builder->get_widget("bindingsButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::bindingsButton_clicked_cb));
// Admin Button
builder->get_widget("adminButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::adminButton_clicked_cb));
isAdmin = false;
isChanAdmin = false;
// Settings Button
builder->get_widget("settingsButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::settingsButton_clicked_cb));
// About Button
builder->get_widget("aboutButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::aboutButton_clicked_cb));
// Settings Button
builder->get_widget("xmitButton", togglebutton);
togglebutton->signal_toggled().connect(sigc::mem_fun(this, &Mangler::xmitButton_toggled_cb));
// Quick Connect Dialog Buttons
builder->get_widget("qcConnectButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::qcConnectButton_clicked_cb));
builder->get_widget("qcCancelButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::qcCancelButton_clicked_cb));
// Input VU Meter
builder->get_widget("inputVUMeterProgressBar", inputvumeter);
// Quick Mute Options
muteMic = false;
muteSound = false;
builder->get_widget("muteMicCheckButton", checkbutton);
checkbutton->signal_toggled().connect(sigc::mem_fun(this, &Mangler::muteMicCheckButton_toggled_cb));
builder->get_widget("muteSoundCheckButton", checkbutton);
checkbutton->signal_toggled().connect(sigc::mem_fun(this, &Mangler::muteSoundCheckButton_toggled_cb));
// Autoreconnect feature implementation
wantDisconnect = false;
// Feature implementation
motdAlways = false;
/*
* Retreive all menu bar items from builder and set their singal handler
* callbacks. Most of these can use the same callback as their
* corresponding button
*/
builder->get_widget("buttonMenuItem", checkmenuitem);
checkmenuitem->signal_toggled().connect(sigc::mem_fun(this, &Mangler::buttonMenuItem_toggled_cb));
builder->get_widget("hideServerInfoMenuItem", checkmenuitem);
checkmenuitem->signal_toggled().connect(sigc::mem_fun(this, &Mangler::hideServerInfoMenuItem_toggled_cb));
builder->get_widget("hideGuestFlagMenuItem", checkmenuitem);
checkmenuitem->signal_toggled().connect(sigc::mem_fun(this, &Mangler::hideGuestFlagMenuItem_toggled_cb));
builder->get_widget("quickConnectMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::quickConnectButton_clicked_cb));
builder->get_widget("serverListMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::serverListButton_clicked_cb));
builder->get_widget("adminLoginMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::adminLoginMenuItem_activate_cb));
builder->get_widget("adminWindowMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::adminWindowMenuItem_activate_cb));
builder->get_widget("settingsMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::settingsButton_clicked_cb));
builder->get_widget("statusIconSettingsMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::settingsButton_clicked_cb));
builder->get_widget("commentMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::commentButton_clicked_cb));
builder->get_widget("motdMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::motdMenuItem_activate_cb));
builder->get_widget("chatMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::chatButton_clicked_cb));
builder->get_widget("recorderMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::recorderMenuItem_activate_cb));
builder->get_widget("quitMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::quitMenuItem_activate_cb));
builder->get_widget("statusIconQuitMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::quitMenuItem_activate_cb));
builder->get_widget("aboutMenuItem", menuitem);
menuitem->signal_activate().connect(sigc::mem_fun(this, &Mangler::aboutButton_clicked_cb));
// connect the signal for our error dialog button
builder->get_widget("errorOKButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::errorOKButton_clicked_cb));
// Set up our message of the day window
builder->get_widget("motdWindow", motdWindow);
builder->get_widget("motdNotebook", motdNotebook);
motdNotebook->set_current_page(1);
motdNotebook->set_show_tabs(false);
builder->get_widget("motdUsers", motdUsers);
builder->get_widget("motdGuests", motdGuests);
builder->get_widget("motdIgnore", motdIgnore);
motdIgnore->signal_toggled().connect(sigc::mem_fun(this, &Mangler::motdIgnore_toggled_cb));
builder->get_widget("motdOkButton", motdOkButton);
motdOkButton->signal_clicked().connect(sigc::mem_fun(this, &Mangler::motdOkButton_clicked_cb));
// Set up our generic password dialog box
builder->get_widget("passwordDialog", passwordDialog);
builder->get_widget("passwordEntry", passwordEntry);
builder->get_widget("passwordOkButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::passwordDialogOkButton_clicked_cb));
builder->get_widget("passwordCancelButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::passwordDialogCancelButton_clicked_cb));
// Set up our kick/ban reason entry dialog box
builder->get_widget("reasonDialog", reasonDialog);
builder->get_widget("reasonEntry", reasonEntry);
builder->get_widget("reasonOkButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::reasonDialogOkButton_clicked_cb));
builder->get_widget("reasonCancelButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::reasonDialogCancelButton_clicked_cb));
// Set up the text string change dialog box
builder->get_widget("textStringChangeDialog", textStringChangeDialog);
builder->get_widget("textStringChangeCommentEntry", textStringChangeCommentEntry);
builder->get_widget("textStringChangeURLEntry", textStringChangeURLEntry);
builder->get_widget("textStringChangeIntegrationEntry", textStringChangeIntegrationEntry);
builder->get_widget("textStringSilenceCommentCheckButton", textStringSilenceCommentCheckButton);
builder->get_widget("textStringOkButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::textStringChangeDialogOkButton_clicked_cb));
builder->get_widget("textStringCancelButton", button);
button->signal_clicked().connect(sigc::mem_fun(this, &Mangler::textStringChangeDialogCancelButton_clicked_cb));
// Create Channel Tree
channelTree = new ManglerChannelTree(builder);
// Create Network Communication Object
network = new ManglerNetwork(builder);
// Create settings object, load the configuration file, and apply. If the
// user has PTT key/mouse enabled, start a timer here
settings = new ManglerSettings(builder);
isTransmittingButton = 0;
isTransmittingVA = 0;
isTransmittingMouse = 0;
isTransmittingKey = 0;
isTransmitting = 0;
Glib::signal_timeout().connect(sigc::mem_fun(this, &Mangler::checkPushToTalkKeys), 100);
Glib::signal_timeout().connect(sigc::mem_fun(this, &Mangler::checkVoiceActivation), 100);
Glib::signal_timeout().connect(sigc::mem_fun(this, &Mangler::checkPushToTalkMouse), 100);
// Create our audio control object for managing devices
audioControl = new ManglerAudio(AUDIO_CONTROL);
audioControl->getDeviceList(config["AudioSubsystem"].toUString());
// If we have eSpeak, go ahead and initialize it
#ifdef HAVE_ESPEAK
if ((espeakRate = espeak_Initialize(AUDIO_OUTPUT_RETRIEVAL, 0, NULL, espeakEVENT_LIST_TERMINATED)) < 0) {
fprintf(stderr, "espeak: initialize error\n");
return;
}
#endif
// set saved window size from settings
unsigned windowWidth( config["WindowWidth"].toUInt() );
unsigned windowHeight( config["WindowHeight"].toUInt() );
if (windowWidth > 0 && windowHeight > 0) manglerWindow->set_default_size(windowWidth, windowHeight);
// set the master volume
v3_set_volume_master(config["MasterVolumeLevel"].toUInt());
v3_set_volume_xmit(config["InputGainLevel"].toUInt());
builder->get_widget("buttonMenuItem", checkmenuitem);
checkmenuitem->set_active(config["ButtonsHidden"].toBool());
builder->get_widget("hideServerInfoMenuItem", checkmenuitem);
checkmenuitem->set_active(config["ServerInfoHidden"].toBool());
builder->get_widget("hideGuestFlagMenuItem", checkmenuitem);
checkmenuitem->set_active(config["GuestFlagHidden"].toBool());
// Create Server List Window
serverList = new ManglerServerList(builder);
// Create Chat Window
chat = new ManglerChat(builder);
// Create Admin Window
admin = new ManglerAdmin(builder);
wantAdminWindow = false;
// Create Recording Window
recorder = new ManglerRecorder(builder);
// Add our servers to the main window drop down
builder->get_widget("serverSelectComboBox", combobox);
combobox->set_model(serverList->serverListTreeModel);
combobox->pack_start(serverList->serverListColumns.name);
Gtk::CellRendererText *renderer = (Gtk::CellRendererText*)(*(combobox->get_cells().begin()));
renderer->property_ellipsize() = Pango::ELLIPSIZE_END;
int serverSelection = 0, ctr = 0;
iniFile::iterator server = config.servers.begin();
while (server != config.servers.end()) {
Gtk::TreeRow row = *(serverList->serverListTreeModel->append());
// is this id useful at all?
row[serverList->serverListColumns.id] = ctr;
row[serverList->serverListColumns.name] = Glib::locale_to_utf8(server->first);
row[serverList->serverListColumns.hostname] = server->second["Hostname"].toUString();
row[serverList->serverListColumns.port] = server->second["Port"].toUString();
row[serverList->serverListColumns.username] = server->second["Username"].toUString();
if (config["LastConnectedServerName"] == server->first) {
serverSelection = ctr;
}
server++; ++ctr;
}
// Select the last one used (or the first if unknown)
combobox->set_active(serverSelection);
// Status Tray Icon
statusIcon = Gtk::StatusIcon::create(icons["tray_icon_grey"]);
statusIcon->signal_activate().connect(sigc::mem_fun(this, &Mangler::statusIcon_activate_cb));
statusIcon->signal_scroll_event().connect_notify(sigc::mem_fun(this, &Mangler::statusIcon_scroll_event_cb));
statusIcon->signal_button_press_event().connect_notify(sigc::mem_fun(this, &Mangler::statusIcon_buttonpress_event_cb));
builder->get_widget("statusIconMenu", statusIconMenu);
builder->get_widget("muteMicCheckMenuItem", checkmenuitem);
checkmenuitem->signal_toggled().connect(sigc::mem_fun(this, &Mangler::muteMicCheckMenuItem_toggled_cb));
checkmenuitem->set_active(config["MuteMic"].toBool());
builder->get_widget("muteSoundCheckMenuItem", checkmenuitem);
checkmenuitem->signal_toggled().connect(sigc::mem_fun(this, &Mangler::muteSoundCheckMenuItem_toggled_cb));
checkmenuitem->set_active(config["MuteSound"].toBool());
iconified = false;
setTooltip();
// Music (Now playing)
integration = new ManglerIntegration();
//integration->setClient((MusicClient)settings->config.AudioIntegrationPlayer);
// TODO: MusicClient? wants a const char *??
integration->setClient((MusicClient)config["AudioIntegrationPlayer"].toUInt());
integration->update(true);
#ifdef HAVE_XOSD
// Create XOSD Overlay
osd = new ManglerOsd();
#endif
#ifdef HAVE_G15
// Create G15 Keyboard LCD Handler
g15 = new ManglerG15();
#endif
Glib::signal_timeout().connect(sigc::mem_fun(this, &Mangler::updateIntegration), 1000);
Glib::signal_timeout().connect(sigc::mem_fun(*this, &Mangler::updateXferAmounts), 500);
Glib::signal_timeout().connect(sigc::mem_fun(*this, &Mangler::getNetworkEvent), 10);
}/*}}}*/
Mangler::~Mangler() {/*{{{*/
delete channelTree;
delete network;
delete settings;
delete audioControl;
delete serverList;
delete chat;
delete admin;
delete recorder;
delete integration;
#ifdef HAVE_XOSD
delete osd;
#endif
#ifdef HAVE_G15
delete g15;
#endif
}/*}}}*/
/*
* Main Window Callbacks
*/
void Mangler::mangler_show_cb(void) {/*{{{*/
if (options) {
// Command Line Quick Connect
if (!options->qc_server.empty()) {
Glib::ustring::size_type separator = options->qc_server.find_last_of(":");
if (separator > 0 && options->qc_server.length() != separator + 1 && options->qc_username.length()) {
onConnectHandler(
options->qc_server.substr(0, separator),
options->qc_server.substr(separator + 1),
options->qc_username,
options->qc_password);
}
}
options = NULL;
}
}/*}}}*/
bool Mangler::mangler_quit_cb(void) {/*{{{*/
int w, h;
manglerWindow->get_size(w, h);
config["WindowWidth"] = w;
config["WindowHeight"] = h;
config.save();
return true;
}/*}}}*/
/*
* Connection Handling
*/
void Mangler::onConnectHandler(
Glib::ustring hostname,
Glib::ustring port,
Glib::ustring username,
Glib::ustring password,
Glib::ustring phonetic,
Glib::ustring charset,
bool acceptPages,
bool acceptU2U,
bool acceptPrivateChat,
bool allowRecording) {/*{{{*/
set_charset(charset);
isAdmin = false;
isChanAdmin = false;
v3_set_server_opts(V3_USER_ACCEPT_PAGES, acceptPages);
v3_set_server_opts(V3_USER_ACCEPT_U2U, acceptU2U);
v3_set_server_opts(V3_USER_ACCEPT_CHAT, acceptPrivateChat);
v3_set_server_opts(V3_USER_ALLOW_RECORD, allowRecording);
channelTree->updateLobby("Connecting...");
Glib::Thread::create(sigc::bind(sigc::mem_fun(this->network, &ManglerNetwork::connect), hostname, port, username, password, phonetic), FALSE);
}/*}}}*/
void Mangler::onDisconnectHandler(void) {/*{{{*/
Gtk::Button *connectbutton;
builder->get_widget("connectButton", connectbutton);
if (connectbutton->get_label() == "gtk-disconnect") {
builder->get_widget("adminButton", button);
button->set_sensitive(false);
builder->get_widget("adminLoginMenuItem", menuitem);
menuitem->set_label("_Admin Login");
menuitem->set_sensitive(false);
builder->get_widget("adminWindowMenuItem", menuitem);
menuitem->set_sensitive(false);
builder->get_widget("chatButton", button);
button->set_sensitive(false);
builder->get_widget("motdMenuItem", menuitem);
menuitem->set_sensitive(false);
builder->get_widget("chatMenuItem", menuitem);
menuitem->set_sensitive(false);
builder->get_widget("commentButton", button);
button->set_sensitive(false);
builder->get_widget("commentMenuItem", menuitem);
menuitem->set_sensitive(false);
isTransmittingMouse = false;
isTransmittingKey = false;
isTransmittingVA = false;
isTransmittingButton = false;
stopTransmit();
connectbutton->set_sensitive(true);
#ifdef HAVE_XOSD
osd->destroyOsd();
#endif
outputAudio.clear();
channelTree->clear();
admin->hide();
admin->clear();
builder->get_widget("xmitButton", togglebutton);
togglebutton->set_active(false);
builder->get_widget("progressbar", progressbar);
progressbar->set_text("");
progressbar->set_fraction(0);
progressbar->hide();
builder->get_widget("statusbar", statusbar);
statusbar->pop();
statusbar->push("Disconnected");
//builder->get_widget("serverTabLabel", label);
//label->set_label("Not Connected");
builder->get_widget("pingLabel", label);
label->set_label("N/A");
builder->get_widget("userCountLabel", label);
label->set_label("N/A");
builder->get_widget("codecLabel", label);
label->set_label("N/A");
mangler->statusIcon->set(icons["tray_icon_grey"]);
isAdmin = false;
isChanAdmin = false;
wantAdminWindow = false;
motdWindow->hide();
motdNotebook->set_current_page(1);
motdNotebook->set_show_tabs(false);
motdUsers->get_buffer()->set_text("");
motdGuests->get_buffer()->set_text("");
chat->clear();
recorder->can_record(false);
if (! connectedServerName.empty()) {
iniSection &server(config.servers[connectedServerName]);
connectedServerName = "";
if (!wantDisconnect && server["PersistentConnection"].toBool()) {
connectbutton->set_label("gtk-cancel");
lastAttempt = time(NULL);
Glib::signal_timeout().connect_seconds(sigc::mem_fun(*this, &Mangler::reconnectStatusHandler), 1);
return;
}
}
}
connectbutton->set_label("gtk-connect");
builder->get_widget("serverSelectComboBox", combobox);
combobox->set_sensitive(true);
}/*}}}*/
bool Mangler::reconnectStatusHandler(void) {/*{{{*/
Gtk::Button *connectbutton;
char buf[64] = "";
int reconnectTimer = (15 - (time(NULL) - lastAttempt));
builder->get_widget("connectButton", connectbutton);
if (connectbutton->get_label() != "gtk-cancel" || wantDisconnect) {
return false;
}
builder->get_widget("statusbar", statusbar);
snprintf(buf, 63, "Attempting reconnect in %d seconds...", (reconnectTimer < 0) ? 0 : reconnectTimer);
statusbar->pop();
statusbar->push(buf);
if (reconnectTimer <= 0) {
lastAttempt = time(NULL);
connectbutton->set_label("gtk-connect");
Mangler::connectButton_clicked_cb();
return false;
}
return true;
}/*}}}*/
/*
* Button signal handler callbacks
*/
void Mangler::quickConnectButton_clicked_cb(void) {/*{{{*/
builder->get_widget("quickConnectDialog", dialog);
dialog->set_icon(icons["tray_icon"]);
builder->get_widget("qcServerName", entry);
entry->set_text(config["qc_lastserver.hostname"].toCString());
builder->get_widget("qcPort", entry);
entry->set_text(config["qc_lastserver.port"].toCString());
builder->get_widget("qcUsername", entry);
entry->set_text(config["qc_lastserver.username"].toCString());
builder->get_widget("qcPassword", entry);
entry->set_text(config["qc_lastserver.password"].toCString());
builder->get_widget("qcConnectButton", button);
button->set_sensitive(!v3_is_loggedin());
dialog->set_keep_above(true);
dialog->run();
dialog->hide();
}/*}}}*/
void Mangler::serverListButton_clicked_cb(void) {/*{{{*/
builder->get_widget("serverListWindow", window);
window->set_icon(icons["tray_icon"]);
window->show();
}/*}}}*/
void Mangler::connectButton_clicked_cb(void) {/*{{{*/
Gtk::Button *connectbutton;
Gtk::TreeModel::iterator iter;
builder->get_widget("connectButton", connectbutton);
if (connectbutton->get_label() == "gtk-cancel") {
wantDisconnect = true;
onDisconnectHandler();
builder->get_widget("statusbar", statusbar);
statusbar->pop();
statusbar->push("Disconnected");
} else if (connectbutton->get_label() == "gtk-connect") {
builder->get_widget("serverSelectComboBox", combobox);
iter = combobox->get_active();
if (iter) {
Gtk::TreeModel::Row row = *iter;
connectedServerName = Glib::ustring( row[serverList->serverListColumns.name] );
iniSection &server(config.servers[connectedServerName]);
Glib::ustring hostname = server["hostname"].toCString();
Glib::ustring port = server["port"].toCString();
Glib::ustring username = server["username"].toCString();
Glib::ustring password = server["password"].toCString();
Glib::ustring phonetic = server["phonetic"].toCString();
if (!server.size() || hostname.empty() || port.empty() || username.empty()) {
builder->get_widget("statusbar", statusbar);
statusbar->pop();
statusbar->push("Not connected.");
if (hostname.empty()) {
errorDialog("You have not specified a hostname for this server.");
return;
}
if (port.empty()) {
errorDialog("You have not specified a port for this server.");
return;
}
if (username.empty()) {
errorDialog("You have not specified a username for this server.");
return;
}
return;
}
config["LastConnectedServerName"] = connectedServerName;
config.config.save();
wantDisconnect = false;
onConnectHandler(
hostname,
port,
username,
password,
phonetic,
server["Charset"].toUString(),
server["acceptPages"].length() ? server["acceptPages"].toBool() : true,
server["acceptU2U"].length() ? server["acceptU2U"].toBool() : true,
server["acceptPrivateChat"].length() ? server["acceptPrivateChat"].toBool() : true,
server["allowRecording"].length() ? server["allowRecording"].toBool() : true);
}
} else {
wantDisconnect = true;
v3_logout();
}
return;
}/*}}}*/
void Mangler::commentButton_clicked_cb(void) {/*{{{*/
if (v3_is_loggedin()) {
textStringChangeCommentEntry->set_text(comment);
textStringChangeURLEntry->set_text(url);
textStringChangeIntegrationEntry->set_text(integration_text);
textStringChangeDialog->run();
textStringChangeDialog->hide();
}
}/*}}}*/
void Mangler::chatButton_clicked_cb(void) {/*{{{*/
if (v3_is_loggedin()) {
if (!chat->isOpen) {
chat->chatWindow->set_icon(icons["tray_icon"]);
chat->chatWindow->show();
} else {
chat->chatWindow->present();
}
}
}/*}}}*/
void Mangler::bindingsButton_clicked_cb(void) {/*{{{*/
//fprintf(stderr, "bindings button clicked\n");
static Glib::ustring color = "red";
if (color == "red") {
color = "green";
statusIcon->set(icons["tray_icon_green"]);
} else if (color == "green") {
color = "blue";
statusIcon->set(icons["tray_icon_blue"]);
} else if (color == "blue") {
color = "yellow";
statusIcon->set(icons["tray_icon_yellow"]);
} else if (color == "yellow") {
color = "red";
statusIcon->set(icons["tray_icon_red"]);
}
}/*}}}*/
void Mangler::adminButton_clicked_cb(void) {/*{{{*/
Glib::ustring password;
if (! isAdmin) {
password = mangler->getPasswordEntry("Admin Password");
if (password.length()) {
v3_admin_login((char *)password.c_str());
wantAdminWindow = true;
// if we tried sending a password, the only options are either
// success or get booted from the server.
}
} else {
admin->show();
}
}/*}}}*/
void Mangler::adminLoginMenuItem_activate_cb(void) {/*{{{*/
builder->get_widget("adminLoginMenuItem", menuitem);
if (menuitem->get_label() == "_Admin Logout") {
v3_admin_logout();
} else {
adminButton_clicked_cb();
}
}/*}}}*/
void Mangler::adminWindowMenuItem_activate_cb(void) {/*{{{*/
admin->show();
}/*}}}*/
void Mangler::settingsButton_clicked_cb(void) {/*{{{*/
settings->settingsWindow->show();
}/*}}}*/
void Mangler::aboutButton_clicked_cb(void) {/*{{{*/
builder->get_widget("aboutWindow", aboutdialog);
aboutdialog->set_keep_above(true);
aboutdialog->set_logo(icons["mangler_logo"]);
aboutdialog->run();
aboutdialog->hide();
}/*}}}*/
void Mangler::xmitButton_toggled_cb(void) {/*{{{*/
builder->get_widget("xmitButton", togglebutton);
if (togglebutton->get_active()) {
isTransmittingButton = true;
startTransmit();
} else {
isTransmittingButton = false;
if (! isTransmittingKey && ! isTransmittingMouse && ! isTransmittingVA) {
stopTransmit();
}
}
}/*}}}*/
/*
* Menu bar signal handler callbacks
*/
void Mangler::buttonMenuItem_toggled_cb(void) {/*{{{*/
builder->get_widget("buttonMenuItem", checkmenuitem);
builder->get_widget("mainWindowButtonVBox", vbox);
if (checkmenuitem->get_active()) {
vbox->hide();
config["ButtonsHidden"] = true;
} else {
config["ButtonsHidden"] = false;
vbox->show();
}
config.config.save();
}/*}}}*/
void Mangler::hideServerInfoMenuItem_toggled_cb(void) {/*{{{*/
builder->get_widget("hideServerInfoMenuItem", checkmenuitem);
builder->get_widget("serverTable", table);
if (checkmenuitem->get_active()) {
table->hide();
config["ServerInfoHidden"] = true;
} else {
config["ServerInfoHidden"] = false;
table->show();
}
config.config.save();
}/*}}}*/
void Mangler::hideGuestFlagMenuItem_toggled_cb(void) {/*{{{*/
builder->get_widget("hideGuestFlagMenuItem", checkmenuitem);
if (checkmenuitem->get_active()) {
config["GuestFlagHidden"] = true;
} else {
config["GuestFlagHidden"] = false;
}
channelTree->refreshAllUsers();
config.config.save();
}/*}}}*/
void Mangler::motdMenuItem_activate_cb(void) {/*{{{*/
motdIgnore->set_sensitive(!connectedServerName.empty());
motdIgnore->set_active(connectedServerName.length() && config.servers[connectedServerName]["MotdIgnore"].toBool());
motdOkButton->grab_focus();
motdWindow->present();
}/*}}}*/
void Mangler::recorderMenuItem_activate_cb(void) {/*{{{*/
recorder->recWindow->set_icon(icons["tray_icon"]);
recorder->show();
}/*}}}*/
void Mangler::quitMenuItem_activate_cb(void) {/*{{{*/
Gtk::Main::quit();
}/*}}}*/
/*
* Other signal handler callbacks
*/
void Mangler::statusIcon_activate_cb(void) {/*{{{*/
if (iconified == true) {
manglerWindow->deiconify();
manglerWindow->present();
manglerWindow->set_skip_pager_hint(false);
manglerWindow->set_skip_taskbar_hint(false);
iconified = false;
} else {
manglerWindow->iconify();
manglerWindow->set_skip_pager_hint(true);
manglerWindow->set_skip_taskbar_hint(true);
iconified = true;
}
}/*}}}*/
void Mangler::statusIcon_buttonpress_event_cb(GdkEventButton* event) {/*{{{*/
if ((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) {
builder->get_widget("statusIconMenu", statusIconMenu);
builder->get_widget("muteMicCheckButton", checkbutton);
builder->get_widget("muteMicCheckMenuItem", checkmenuitem);
checkmenuitem->set_active(checkbutton->get_active());
builder->get_widget("muteSoundCheckButton", checkbutton);
builder->get_widget("muteSoundCheckMenuItem", checkmenuitem);
checkmenuitem->set_active(checkbutton->get_active());
statusIconMenu->popup(event->button, event->time);
}
}
/*}}}*/
void Mangler::statusIcon_scroll_event_cb(GdkEventScroll* event) {/*{{{*/
if (event->type != GDK_SCROLL) {
return;
}
int volume = config["MasterVolumeLevel"].toInt();
switch (event->direction) {
case GDK_SCROLL_UP:
volume = (volume + 5 > 148) ? 148 : volume + 5;
break;
case GDK_SCROLL_DOWN:
volume = (volume - 5 < 0) ? 0 : volume - 5;
break;
default:
return;
}
if (volume + 5 > 79 && volume - 5 < 79) {
volume = 79;
}
config["MasterVolumeLevel"] = volume;
settings->volumeAdjustment->set_value(volume);
v3_set_volume_master(volume);
setTooltip();
}/*}}}*/
void Mangler::setTooltip(void) {/*{{{*/
Glib::ustring tooltip = "Mangler: volume: ";
float value = config["MasterVolumeLevel"].toInt();
value = (value > 79) ? ((value-79)/69)*100+100 : (value/79)*100;
tooltip += Glib::ustring::format((int)value) + "%" + ((config["MuteSound"].toBool()) ? " (muted)" : "");
statusIcon->set_tooltip_text(tooltip);
}/*}}}*/
void Mangler::startTransmit(void) {/*{{{*/
const v3_codec *codec;
v3_user *user;
if (! v3_is_loggedin()) {
return;
}
if (muteMic) {
return;
}
user = v3_get_user(v3_get_user_id());
if (! user) {
return;
}
if (isTransmitting) {
v3_free_user(user);
return;
}
isTransmitting = true;
if ((codec = v3_get_channel_codec(user->channel))) {
//fprintf(stderr, "channel %d codec rate: %d at sample size %d\n", user->channel, codec->rate, codec->pcmframesize);
v3_free_user(user);
channelTree->setUserIcon(v3_get_user_id(), "orange");
statusIcon->set(icons["tray_icon_yellow"]);
inputAudio = new ManglerAudio(AUDIO_INPUT, codec->rate, 1, codec->pcmframesize);
}
}/*}}}*/
void Mangler::stopTransmit(void) {/*{{{*/
if (!isTransmitting) {
return;
}
isTransmitting = false;
if (v3_is_loggedin()) {
channelTree->setUserIcon(v3_get_user_id(), "red");
statusIcon->set(icons["tray_icon_red"]);
}
if (inputAudio) {
inputAudio->finish();
inputAudio = NULL;
}
}/*}}}*/
// Quick Sound Mute
void Mangler::muteSoundCheckButton_toggled_cb(void) {/*{{{*/
builder->get_widget("muteSoundCheckButton", checkbutton);
muteSound = checkbutton->get_active();
config["MuteSound"] = muteSound;
setTooltip();
}/*}}}*/
// Quick Mic Mute
void Mangler::muteMicCheckButton_toggled_cb(void) {/*{{{*/
builder->get_widget("muteMicCheckButton", checkbutton);
muteMic = checkbutton->get_active();
config["MuteMic"] = muteMic;
if (muteMic && isTransmitting) {
stopTransmit();
} else if (!muteMic && (isTransmittingMouse || isTransmittingKey || isTransmittingButton || isTransmittingVA)) {
startTransmit();
}
}/*}}}*/
// Status Icon Sound Mute
void Mangler::muteSoundCheckMenuItem_toggled_cb(void) {/*{{{*/
builder->get_widget("muteSoundCheckButton", checkbutton);
builder->get_widget("muteSoundCheckMenuItem", checkmenuitem);
checkbutton->set_active(checkmenuitem->get_active());
}/*}}}*/
// Status Icon Mic Mute
void Mangler::muteMicCheckMenuItem_toggled_cb(void) {/*{{{*/
builder->get_widget("muteMicCheckButton", checkbutton);
builder->get_widget("muteMicCheckMenuItem", checkmenuitem);
checkbutton->set_active(checkmenuitem->get_active());
}/*}}}*/
// Quick Connect Callbacks
void Mangler::qcConnectButton_clicked_cb(void) {/*{{{*/
builder->get_widget("qcServerName", entry);
Glib::ustring hostname = entry->get_text();
builder->get_widget("qcPort", entry);
Glib::ustring port = entry->get_text();
builder->get_widget("qcUsername", entry);
Glib::ustring username = entry->get_text();
builder->get_widget("qcPassword", entry);
Glib::ustring password = entry->get_text();
//fprintf(stderr, "connecting to: %s:%s\n", server.c_str(), port.c_str());
config["qc_lastserver.hostname"] = hostname;
config["qc_lastserver.port"] = port;
config["qc_lastserver.username"] = username;
config["qc_lastserver.password"] = password;
config.config.save();
connectedServerName = "";
onConnectHandler(hostname, port, username, password);
}/*}}}*/
void Mangler::qcCancelButton_clicked_cb(void) {/*{{{*/
}/*}}}*/
// MOTD Window Callbacks
void Mangler::motdIgnore_toggled_cb(void) {/*{{{*/
if (connectedServerName.length()) {
config.servers[connectedServerName]["MotdIgnore"] = motdIgnore->get_active();
}
}/*}}}*/
void Mangler::motdOkButton_clicked_cb(void) {/*{{{*/
motdWindow->hide();
}/*}}}*/
/*
* Timeout Callbacks
*
* Inbound event processing happens here.
*/
bool Mangler::getNetworkEvent() {/*{{{*/
v3_event *ev;
while ((ev = v3_get_event(V3_NONBLOCK)) != NULL) {
v3_user *u;
v3_channel *c;
Glib::ustring rank = "";
gdk_threads_enter();
// if we're not logged in, just ignore whatever messages we receive
// *unless* it's a disconnect message. This prevents old messages in
// the queue from attempting to interact with the GUI after a
// disconnection
switch (ev->type) {
case V3_EVENT_PING:/*{{{*/
if (v3_is_loggedin()) {
char buf[64];
builder->get_widget("pingLabel", label);
builder->get_widget("statusbar", statusbar);
if (ev->ping != 65535) {
snprintf(buf, 16, "%dms", ev->ping);
#ifdef HAVE_G15
g15->update("", "", "", "", buf);
#endif
label->set_text(c_to_ustring(buf));
snprintf(buf, 63, "Ping: %dms - Users: %d/%d", ev->ping, v3_user_count(), v3_get_max_clients());
statusbar->pop();
statusbar->push(c_to_ustring(buf));
} else {
#ifdef HAVE_G15
g15->update("", "", "", "", "checking...");
#endif
label->set_text("checking...");
snprintf(buf, 63, "Ping: checking... - Users: %d/%d", v3_user_count(), v3_get_max_clients());
statusbar->pop();
statusbar->push(c_to_ustring(buf));
}
builder->get_widget("userCountLabel", label);
snprintf(buf, 16, "%d/%d", v3_user_count(), v3_get_max_clients());
label->set_text(c_to_ustring(buf));
}
break;/*}}}*/
case V3_EVENT_STATUS:/*{{{*/
if (v3_is_loggedin()) {
builder->get_widget("progressbar", progressbar);
builder->get_widget("statusbar", statusbar);
if (ev->status.percent == 100) {
progressbar->hide();
} else {
progressbar->show();
progressbar->set_fraction(ev->status.percent/(float)100);
}
statusbar->pop();
statusbar->push(ev->status.message);
//fprintf(stderr, "got event type %d: %d %s\n", ev->type, ev->status.percent, ev->status.message);
}
break;/*}}}*/
case V3_EVENT_USER_LOGIN:/*{{{*/
u = v3_get_user(ev->user.id);
if (!u) {
fprintf(stderr, "couldn't retreive user id %d\n", ev->user.id);
break;
}
if (!(ev->flags & V3_LOGIN_FLAGS_EXISTING) && (v3_get_user_channel(v3_get_user_id()) == ev->channel.id)) {
audioControl->playNotification("channelenter");
}
#ifdef HAVE_G15
if (!(ev->flags & V3_LOGIN_FLAGS_EXISTING)) {
g15->update("", "", u->name, "", "");
}
#endif
//fprintf(stderr, "adding user id %d: %s to channel %d\n", ev->user.id, u->name, ev->channel.id);
if (u->rank_id) {
v3_rank *r;
if ((r = v3_get_rank(u->rank_id))) {
rank = c_to_ustring(r->name);
v3_free_rank(r);
}
}
channelTree->addUser(
(uint32_t)u->id,
(uint32_t)ev->channel.id,
c_to_ustring(u->name),
c_to_ustring(u->comment),
u->phonetic,
u->url,
c_to_ustring(u->integration_text),
(bool)u->guest,
(bool)u->real_user_id,
rank);
if (connectedServerName.length() && u->id != v3_get_user_id()) {
// If we have a per user volume set for this user name, set it now.
if (config.hasUserVolume(connectedServerName, u->name)) {
v3_set_volume_user(u->id, config.UserVolume(connectedServerName, u->name).toInt());
}
// If the user was muted, mute them again.
if (config.UserMuted(connectedServerName, u->name).toBool()) {
channelTree->muteUserToggle(u->id);
}
}
v3_free_user(u);
break;/*}}}*/
case V3_EVENT_USER_MODIFY:/*{{{*/
if (v3_is_loggedin()) {
u = v3_get_user(ev->user.id);
if (!u) {
fprintf(stderr, "couldn't retreive user id %d\n", ev->user.id);
break;
}
if (u->id == 0) {
channelTree->updateLobby(c_to_ustring(u->name), c_to_ustring(u->comment), c_to_ustring(u->phonetic));
} else {
if (u->rank_id) {
v3_rank *r;
if ((r = v3_get_rank(u->rank_id))) {
rank = c_to_ustring(r->name);
v3_free_rank(r);
}
}
channelTree->updateUser(
(uint32_t)u->id,
(uint32_t)ev->channel.id,
c_to_ustring(u->name),
c_to_ustring(u->comment),
u->phonetic,
u->url,
c_to_ustring(u->integration_text),
(bool)u->guest,
(bool)u->real_user_id,
rank);
}
v3_free_user(u);
}
break;/*}}}*/
case V3_EVENT_CHAN_MODIFY:/*{{{*/
if (v3_is_loggedin()) {
const v3_codec *codec_info;
c = v3_get_channel(ev->channel.id);
if (!c) {
fprintf(stderr, "couldn't retreive channel id %d\n", ev->user.id);
break;
}
channelTree->updateChannel(
(uint8_t)c->protect_mode,
(uint32_t)c->id,
(uint32_t)c->parent,
c_to_ustring(c->name),
c_to_ustring(c->comment),
c->phonetic);
if (! isAdmin && ! isChanAdmin && v3_is_channel_admin(c->id)) {
isChanAdmin = true;
}
admin->channelUpdated(c);
if (ev->channel.id == v3_get_user_channel(v3_get_user_id())) {
builder->get_widget("codecLabel", label);
if ((codec_info = v3_get_channel_codec(ev->channel.id))) {
label->set_text(codec_info->name);
} else {
label->set_text("Unsupported Codec");
}
}
v3_free_channel(c);
}
break;/*}}}*/
case V3_EVENT_USER_LOGOUT:/*{{{*/
if (v3_is_loggedin()) {
if (outputAudio[ev->user.id]) {
outputAudio[ev->user.id]->finish();
outputAudio.erase(ev->user.id);
}
if (v3_get_user_channel(v3_get_user_id()) == ev->channel.id) {
audioControl->playNotification("channelleave");
}
// can't get any user info... it's already gone by this point
//fprintf(stderr, "removing user id %d\n", ev->user.id);
channelTree->removeUser(ev->user.id);
chat->removeUser(ev->user.id);
#ifdef HAVE_XOSD
osd->removeUser(ev->user.id);
#endif
}
break;/*}}}*/
case V3_EVENT_CHAN_REMOVE:/*{{{*/
if (v3_is_loggedin()) {
// can't get any channel info... it's already gone by this point
//fprintf(stderr, "removing channel id %d\n", ev->channel.id);
channelTree->removeChannel(ev->channel.id);
admin->channelRemoved(ev->channel.id);
}
break;/*}}}*/
case V3_EVENT_LOGIN_COMPLETE:/*{{{*/
if (v3_is_loggedin()) {
const v3_codec *codec_info;
builder->get_widget("adminButton", button);
button->set_sensitive(true);
builder->get_widget("adminLoginMenuItem", menuitem);
menuitem->set_sensitive(true);
builder->get_widget("adminWindowMenuItem", menuitem);
menuitem->set_sensitive(true);
builder->get_widget("chatButton", button);
button->set_sensitive(true);
builder->get_widget("motdMenuItem", menuitem);
menuitem->set_sensitive(true);
builder->get_widget("chatMenuItem", menuitem);
menuitem->set_sensitive(true);
builder->get_widget("commentButton", button);
button->set_sensitive(true);
builder->get_widget("commentMenuItem", menuitem);
menuitem->set_sensitive(true);
builder->get_widget("codecLabel", label);
if ((codec_info = v3_get_channel_codec(0))) {
label->set_text(codec_info->name);
} else {
label->set_text("Unsupported Codec");
}
channelTree->expand_all();
audioControl->playNotification("login");
if (connectedServerName.length()) {
iniSection &server(config.servers[connectedServerName]);
if (server["PersistentComments"].toBool()) {
comment = server["Comment"].toUString();
url = server["URL"].toUString();
v3_set_text(
(char *)ustring_to_c(comment).c_str(),
(char *)ustring_to_c(url).c_str(),
(char *)ustring_to_c(integration_text).c_str(),
true);
}
uint32_t channel_id = v3_get_channel_id(ustring_to_c(server["DefaultChannel"].toUString()).c_str());
if (channel_id && (c = v3_get_channel(channel_id))) {
Glib::ustring password = channelTree->getChannelSavedPassword(channel_id);
uint16_t pw_channel = 0;
if ((pw_channel = v3_channel_requires_password(channel_id)) &&
(password = channelTree->getChannelSavedPassword(pw_channel)).empty() &&
(password = getPasswordEntry("Channel Password")).length()) {
channelTree->setChannelSavedPassword(pw_channel, password);
}
if (!pw_channel || (pw_channel && password.length())) {
v3_change_channel(channel_id, (char *)((pw_channel) ? password.c_str() : ""));
}
v3_free_channel(c);
}
}
if (chat->isOpen) {
v3_join_chat();
}
recorder->can_record(true);
#ifdef HAVE_G15
g15->addevent("connected to server");
g15->update(connectedServerName, "", "", "", "");
#endif
}
break;/*}}}*/
case V3_EVENT_USER_CHAN_MOVE:/*{{{*/
{
u = v3_get_user(ev->user.id);
if (! u) {
fprintf(stderr, "failed to retreive user information for user id %d\n", ev->user.id);
break;
}
if (ev->user.id == v3_get_user_id()) {
// we're moving channels... update the codec label
const v3_codec *codec_info;
builder->get_widget("codecLabel", label);
if ((codec_info = v3_get_channel_codec(ev->channel.id))) {
label->set_text(codec_info->name);
} else {
label->set_text("Unsupported Codec");
}
#ifdef HAVE_G15
if ((c = v3_get_channel(ev->channel.id))) {
string event = "switched to: ";
event.append(c->name);
g15->addevent(event);
free(c);
}
#endif
#ifdef HAVE_XOSD
osd->destroyOsd();
#endif
} else {
if (ev->channel.id == v3_get_user_channel(v3_get_user_id())) {
// they're joining our channel
audioControl->playNotification("channelenter");
#ifdef HAVE_G15
string event = "joined channel: ";
event.append(u->name);
g15->addevent(event);
g15->update("", "", "", u->name, "");
#endif
} else if (channelTree->getUserChannelId(ev->user.id) == v3_get_user_channel(v3_get_user_id())) {
// they're leaving our channel
audioControl->playNotification("channelleave");
#ifdef HAVE_G15
string event = "left channel: ";
event.append(u->name);
g15->addevent(event);
#endif
}
#ifdef HAVE_XOSD
osd->removeUser(ev->user.id);
#endif
}
if (u->rank_id) {
v3_rank *r;
if ((r = v3_get_rank(u->rank_id))) {
rank = c_to_ustring(r->name);
v3_free_rank(r);
}
}
//fprintf(stderr, "moving user id %d to channel id %d\n", ev->user.id, ev->channel.id);
Glib::ustring last_transmit = channelTree->getLastTransmit((uint32_t)ev->user.id);
channelTree->removeUser((uint32_t)ev->user.id);
channelTree->addUser(
(uint32_t)u->id,
(uint32_t)ev->channel.id,
c_to_ustring(u->name),
c_to_ustring(u->comment),
u->phonetic,
u->url,
c_to_ustring(u->integration_text),
(bool)u->guest,
(bool)u->real_user_id,
rank);
channelTree->setLastTransmit(ev->user.id, last_transmit);
if (connectedServerName.length() && u->id != v3_get_user_id()) {
// If we have a per user volume set for this user name, set it now.
if (config.hasUserVolume(connectedServerName, u->name)) {
v3_set_volume_user(u->id, config.UserVolume(connectedServerName, u->name).toInt());
}
// If the user was muted, mute them again.
if (config.UserMuted(connectedServerName, u->name).toBool()) {
channelTree->muteUserToggle(u->id);
}
}
// if there was an audio stream open for this user, close it
if (outputAudio[ev->user.id]) {
outputAudio[ev->user.id]->finish();
outputAudio.erase(ev->user.id);
}
channelTree->refreshAllUsers();
chat->chatUserTreeModelFilter->refilter();
v3_free_user(u);
}
break;/*}}}*/
case V3_EVENT_CHAN_MOVE:/*{{{*/
channelTree->refreshAllChannels();
admin->channelResort();
break;/*}}}*/
case V3_EVENT_CHAN_ADD:/*{{{*/
c = v3_get_channel(ev->channel.id);
if (! c) {
fprintf(stderr, "failed to retreive channel information for channel id %d\n", ev->channel.id);
break;
}
channelTree->addChannel(
(uint8_t)c->protect_mode,
(uint32_t)c->id,
(uint32_t)c->parent,
c_to_ustring(c->name),
c_to_ustring(c->comment),
c->phonetic);
if (! isAdmin && ! isChanAdmin && v3_is_channel_admin(c->id)) {
isChanAdmin = true;
}
admin->channelAdded(c);
v3_free_channel(c);
break;/*}}}*/
case V3_EVENT_CHAN_BADPASS:/*{{{*/
channelTree->forgetChannelSavedPassword(ev->channel.id);
errorDialog(c_to_ustring(ev->error.message));
break;/*}}}*/
case V3_EVENT_ERROR_MSG:/*{{{*/
errorDialog(c_to_ustring(ev->error.message));
break;/*}}}*/
case V3_EVENT_USER_TALK_START:/*{{{*/
if (v3_is_loggedin()) {
channelTree->refreshUser(ev->user.id);
}
#ifdef HAVE_G15
if (v3_get_user_channel(ev->user.id) == v3_get_user_channel(v3_get_user_id())) {
if ((u = v3_get_user(ev->user.id))) {
string event = "talking: ";
event.append(u->name);
g15->addevent(event);
g15->update("", u->name, "", "", "");
free(u);
}
}
#endif
break;/*}}}*/
case V3_EVENT_USER_TALK_END:
case V3_EVENT_USER_TALK_MUTE:/*{{{*/
if (v3_is_loggedin()) {
channelTree->refreshUser(ev->user.id);
#ifdef HAVE_XOSD
osd->removeUser(ev->user.id);
#endif
if (outputAudio[ev->user.id]) {
outputAudio[ev->user.id]->finish();
outputAudio.erase(ev->user.id);
}
}
break;/*}}}*/
case V3_EVENT_PLAY_AUDIO:/*{{{*/
if (v3_is_loggedin()) {
channelTree->setUserIcon(ev->user.id, "green", true);
#ifdef HAVE_XOSD
osd->addUser(ev->user.id);
#endif
if (!channelTree->isMuted(ev->user.id) && !muteSound) {
// Open a stream if we don't have one for this user
if (!outputAudio[ev->user.id]) {
outputAudio[ev->user.id] = new ManglerAudio(AUDIO_OUTPUT, ev->pcm.rate, ev->pcm.channels);
}
// And queue the audio
if (outputAudio[ev->user.id]) {
outputAudio[ev->user.id]->queue(ev->pcm.length, (uint8_t *)ev->data->sample);
}
} else if (outputAudio[ev->user.id]) {
outputAudio[ev->user.id]->finish();
outputAudio.erase(ev->user.id);
}
}
break;/*}}}*/
case V3_EVENT_RECORD_UPDATE:/*{{{*/
recorder->record(
c_to_ustring(ev->text.name),
c_to_ustring(ev->status.message),
ev->record.index,
ev->record.time,
ev->record.stopped,
ev->record.flushed);
break;/*}}}*/
case V3_EVENT_DISPLAY_MOTD:/*{{{*/
{
Glib::ustring motdKey;
uint32_t motdhash = 0;
if (!ev->flags) {
motdKey = "MotdHashUser";
motdNotebook->set_show_tabs(true);
motdNotebook->set_current_page(0);
motdUsers->get_buffer()->set_text(c_to_ustring(stripMotdRtf(ev->data->motd).c_str()));
} else {
motdKey = "MotdHash";
motdGuests->get_buffer()->set_text(c_to_ustring(stripMotdRtf(ev->data->motd).c_str()));
}
motdIgnore->set_sensitive(!connectedServerName.empty());
motdIgnore->set_active(connectedServerName.length() && config.servers[connectedServerName]["MotdIgnore"].toBool());
if (motdIgnore->get_active() || !strlen(ev->data->motd)) {
break;
}
if (connectedServerName.length()) {
// we're not launching a space shuttle here, no need for
// anything super complex
for (uint32_t ctr = 0; ctr < strlen(ev->data->motd); ctr++) {
motdhash += ev->data->motd[ctr] + ctr;
}
}
if (motdAlways || connectedServerName.empty() || config.servers[connectedServerName][motdKey].toULong() != motdhash) {
if (connectedServerName.length()) {
config.servers[connectedServerName][motdKey] = motdhash;
config.servers.save();
}
motdOkButton->grab_focus();
motdWindow->show();
}
}
break;/*}}}*/
case V3_EVENT_DISCONNECT:/*{{{*/
onDisconnectHandler();
audioControl->playNotification("logout");
break;/*}}}*/
case V3_EVENT_CHAT_JOIN:/*{{{*/
{
chat->addUser(ev->user.id);
u = v3_get_user(ev->user.id);
if (!u) {
fprintf(stderr, "couldn't retreive user id %d\n", ev->user.id);
break;
}
if (u->id != 0) {
if (u->rank_id) {
v3_rank *r;
if ((r = v3_get_rank(u->rank_id))) {
rank = c_to_ustring(r->name);
v3_free_rank(r);
}
}
channelTree->updateUser(
(uint32_t)u->id,
(uint32_t)u->channel,
c_to_ustring(u->name),
c_to_ustring(u->comment),
u->phonetic,
u->url,
c_to_ustring(u->integration_text),
(bool)u->guest,
(bool)u->real_user_id,
rank);
}
v3_free_user(u);
}
break;/*}}}*/
case V3_EVENT_CHAT_LEAVE:/*{{{*/
{
chat->removeUser(ev->user.id);
u = v3_get_user(ev->user.id);
if (!u) {
fprintf(stderr, "couldn't retreive user id %d\n", ev->user.id);
break;
}
if (u->id != 0) {
if (u->rank_id) {
v3_rank *r;
if ((r = v3_get_rank(u->rank_id))) {
rank = c_to_ustring(r->name);
v3_free_rank(r);
}
}
channelTree->updateUser(
(uint32_t)u->id,
(uint32_t)u->channel,
c_to_ustring(u->name),
c_to_ustring(u->comment),
u->phonetic,
u->url,
c_to_ustring(u->integration_text),
(bool)u->guest,
(bool)u->real_user_id,
rank);
}
v3_free_user(u);
}
break;/*}}}*/
case V3_EVENT_CHAT_MESSAGE:/*{{{*/
if (v3_is_loggedin()) {
if (ev->user.id == 0) {
chat->addRconMessage(c_to_ustring(ev->data->chatmessage));
} else {
chat->addChatMessage(ev->user.id, c_to_ustring(ev->data->chatmessage));
}
}
break;/*}}}*/
case V3_EVENT_PRIVATE_CHAT_START:/*{{{*/
{
uint16_t remote;
if (ev->user.privchat_user1 == v3_get_user_id()) {
remote = ev->user.privchat_user2;
} else {
remote = ev->user.privchat_user1;
}
if (privateChatWindows[remote]) {
privateChatWindows[remote]->remoteReopened();
} else {
v3_user *u;
Glib::ustring name = "unknown";
if ((u = v3_get_user(remote)) != NULL) {
name = c_to_ustring(u->name);
v3_free_user(u);
}
privateChatWindows[remote] = new ManglerPrivChat(remote);
privateChatWindows[remote]->addMessage("*** opened private chat with " + name);
}
}
break;/*}}}*/
case V3_EVENT_PRIVATE_CHAT_END:/*{{{*/
{
if (privateChatWindows[ev->user.privchat_user2]) {
privateChatWindows[ev->user.privchat_user2]->remoteClosed();
}
}
break;/*}}}*/
case V3_EVENT_PRIVATE_CHAT_AWAY:/*{{{*/
{
if (privateChatWindows[ev->user.privchat_user2]) {
privateChatWindows[ev->user.privchat_user2]->remoteAway();
}
}
break;/*}}}*/
case V3_EVENT_PRIVATE_CHAT_BACK:/*{{{*/
{
if (privateChatWindows[ev->user.privchat_user2]) {
privateChatWindows[ev->user.privchat_user2]->remoteBack();
}
}
break;/*}}}*/
case V3_EVENT_PRIVATE_CHAT_MESSAGE:/*{{{*/
{
uint16_t remote;
if (ev->user.privchat_user1 == v3_get_user_id()) {
remote = ev->user.privchat_user2;
} else {
remote = ev->user.privchat_user1;
}
if (privateChatWindows[remote]) {
if (!ev->flags) { // set to true on error
privateChatWindows[remote]->addChatMessage(ev->user.privchat_user2, c_to_ustring(ev->data->chatmessage));
} else {
privateChatWindows[remote]->addMessage("*** error sending message to remote user");
}
}
}
break;/*}}}*/
case V3_EVENT_TEXT_TO_SPEECH_MESSAGE:/*{{{*/
{
if ((u = v3_get_user(ev->user.id))) {
//fprintf(stderr, "TTS: %s: %s\n", u->name, ev->data->chatmessage);
audioControl->playText(c_to_ustring((strlen(u->phonetic)) ? u->phonetic : u->name) + ": " + c_to_ustring(ev->data->chatmessage));
v3_free_user(u);
}
}
break;/*}}}*/
case V3_EVENT_PLAY_WAVE_FILE_MESSAGE:/*{{{*/
{
/*
if ((u = v3_get_user(ev->user.id))) {
fprintf(stderr, "WAV: %s: %s\n", u->name, ev->data->chatmessage);
v3_free_user(u);
}
*/
}
break;/*}}}*/
case V3_EVENT_USER_PAGE:/*{{{*/
{
if ((u = v3_get_user(ev->user.id))) {
//fprintf(stderr, "Page from: %s\n", u->name);
audioControl->playText("Page from: " + c_to_ustring((strlen(u->phonetic)) ? u->phonetic : u->name));
v3_free_user(u);
}
}
break;/*}}}*/
case V3_EVENT_ADMIN_AUTH:/*{{{*/
{
const v3_permissions *perms = v3_get_permissions();
if (perms->srv_admin && !isAdmin) {
isAdmin = true;
builder->get_widget("adminLoginMenuItem", menuitem);
menuitem->set_label("_Admin Logout");
if (wantAdminWindow) {
wantAdminWindow = false;
admin->show();
}
} else {
isAdmin = false;
builder->get_widget("adminLoginMenuItem", menuitem);
menuitem->set_label("_Admin Login");
}
v3_user *lobby;
if ((lobby = v3_get_user(0))) {
channelTree->updateLobby(c_to_ustring(lobby->name), c_to_ustring(lobby->comment), c_to_ustring(lobby->phonetic));
v3_free_user(lobby);
}
}
break;/*}}}*/
case V3_EVENT_CHAN_ADMIN_UPDATED:/*{{{*/
channelTree->refreshAllChannels();
break;/*}}}*/
case V3_EVENT_USER_GLOBAL_MUTE_CHANGED:
case V3_EVENT_USER_CHANNEL_MUTE_CHANGED:/*{{{*/
channelTree->refreshUser(ev->user.id);
if (outputAudio[ev->user.id]) {
outputAudio[ev->user.id]->finish();
outputAudio.erase(ev->user.id);
}
break;/*}}}*/
case V3_EVENT_SERVER_PROPERTY_UPDATED:/*{{{*/
switch (ev->serverproperty.property) {
case V3_SRV_PROP_CHAT_FILTER:
chat->isPerChannel = ev->serverproperty.value;
chat->chatUserTreeModelFilter->refilter();
break;
case V3_SRV_PROP_CHAN_ORDER:
channelTree->sortManual = ev->serverproperty.value;
channelTree->refreshAllChannels();
admin->channelSort(ev->serverproperty.value);
break;
case V3_SRV_PROP_MOTD_ALWAYS:
motdAlways = ev->serverproperty.value;
break;
}
break;/*}}}*/
case V3_EVENT_USERLIST_ADD:/*{{{*/
{
v3_account *account = v3_get_account(ev->account.id);
if (account) {
admin->accountAdded(account);
v3_free_account(account);
}
}
break;/*}}}*/
case V3_EVENT_USERLIST_REMOVE:/*{{{*/
admin->accountRemoved(ev->account.id);
break;/*}}}*/
case V3_EVENT_USERLIST_MODIFY:/*{{{*/
{
v3_account *account = v3_get_account(ev->account.id);
if (account) {
admin->accountUpdated(account);
v3_free_account(account);
}
}
break;/*}}}*/
case V3_EVENT_RANK_ADD:/*{{{*/
{
v3_rank *rank = v3_get_rank(ev->data->rank.id);
admin->rankAdded(rank);
}
break;/*}}}*/
case V3_EVENT_RANK_REMOVE:/*{{{*/
{
admin->rankRemoved(ev->data->rank.id);
}
break;/*}}}*/
case V3_EVENT_RANK_MODIFY:/*{{{*/
{
v3_rank *rank = v3_get_rank(ev->data->rank.id);
admin->rankUpdated(rank);
}
break;/*}}}*/
case V3_EVENT_PERMS_UPDATED:/*{{{*/
admin->permsUpdated();
break;/*}}}*/
case V3_EVENT_USER_RANK_CHANGE:/*{{{*/
{
if (v3_is_loggedin()) {
u = v3_get_user(ev->user.id);
if (!u) {
fprintf(stderr, "couldn't retreive user id %d\n", ev->user.id);
break;
}
if (u->id == 0) {
channelTree->updateLobby(c_to_ustring(u->name), c_to_ustring(u->comment), c_to_ustring(u->phonetic));
} else {
if (u->rank_id) {
v3_rank *r;
if ((r = v3_get_rank(u->rank_id))) {
rank = c_to_ustring(r->name);
v3_free_rank(r);
}
}
channelTree->updateUser(
(uint32_t)u->id,
(uint32_t)u->channel,
c_to_ustring(u->name),
c_to_ustring(u->comment),
u->phonetic,
u->url,
c_to_ustring(u->integration_text),
(bool)u->guest,
(bool)u->real_user_id,
rank);
}
v3_free_user(u);
}
}
break;/*}}}*/
case V3_EVENT_SRV_PROP_RECV:/*{{{*/
admin->serverSettingsUpdated(ev->data->srvprop);
break;/*}}}*/
case V3_EVENT_SRV_PROP_SENT:/*{{{*/
admin->serverSettingsSendDone();
break;/*}}}*/
case V3_EVENT_ADMIN_BAN_LIST:/*{{{*/
admin->banList(
ev->data->ban.id,
ev->data->ban.count,
ev->data->ban.bitmask_id,
ev->data->ban.ip_address,
ev->data->ban.user,
ev->data->ban.by,
ev->data->ban.reason);
break;/*}}}*/
default:
fprintf(stderr, "******************************************************** got unknown event type %d\n", ev->type);
}
channelTree->expand_all();
v3_free_event(ev);
gdk_threads_leave();
}
return true;
}/*}}}*/
bool Mangler::checkPushToTalkKeys(void) {/*{{{*/
char pressed_keys[32];
GdkWindow *rootwin = gdk_get_default_root_window();
vector::iterator i;
bool ptt_on = true;
if (! config["PushToTalkKeyEnabled"].toBool()) {
isTransmittingKey = false;
return true;
}
vector ptt_keycodes = config.PushToTalkXKeyCodes();
XQueryKeymap(GDK_WINDOW_XDISPLAY(rootwin), pressed_keys);
for ( i = ptt_keycodes.begin();
i < ptt_keycodes.end();
i++) {
if (!((pressed_keys[*i >> 3] >> (*i & 0x07)) & 0x01)) {
ptt_on = false;
break;
}
}
if (ptt_on) {
isTransmittingKey = true;
startTransmit();
} else {
isTransmittingKey = false;
if (! isTransmittingButton && ! isTransmittingMouse && ! isTransmittingVA) {
stopTransmit();
}
}
return(true);
}/*}}}*/
bool Mangler::checkVoiceActivation(void) {/*{{{*/
if (Mangler::config["VoiceActivationEnabled"].toBool()) {
isTransmittingVA = true;
startTransmit();
} else {
isTransmittingVA = false;
if (! isTransmittingButton && ! isTransmittingMouse && ! isTransmittingKey) {
stopTransmit();
}
}
return true;
}/*}}}*/
bool Mangler::checkPushToTalkMouse(void) {/*{{{*/
GdkWindow *rootwin = gdk_get_default_root_window();
XDeviceInfo *xdev;
XDeviceState *xds;
XButtonState *xbs = NULL;
XInputClass *xic = NULL;
int ctr;
int ndevices_return;
int state = 1;
int byte = config["PushToTalkMouseValue"].toInt() / 8;
int bit = config["PushToTalkMouseValue"].toInt() % 8;
bool ptt_on = false;
if (! config["PushToTalkMouseEnabled"].toBool()) {
isTransmittingMouse = false;
return true;
}
if (config["MouseDeviceName"].empty()) {
return true;
}
if (CurrentOpenMouse != config["MouseDeviceName"].toString()) {
if (dev) {
XCloseDevice(GDK_WINDOW_XDISPLAY(rootwin), dev);
}
xdev = XListInputDevices(GDK_WINDOW_XDISPLAY(rootwin), &ndevices_return);
for (ctr = 0; ctr < ndevices_return; ctr++) {
Glib::ustring name = xdev[ctr].name;
if (config["MouseDeviceName"] == name && xdev[ctr].use == IsXExtensionPointer) {
break;
}
}
if (ctr == ndevices_return) {
XFreeDeviceList(xdev);
return true;
}
dev = XOpenDevice(GDK_WINDOW_XDISPLAY(rootwin), xdev[ctr].id);
XFreeDeviceList(xdev);
if (! dev) {
return true;
}
CurrentOpenMouse = config["MouseDeviceName"].toString();
}
xds = (XDeviceState *)XQueryDeviceState(GDK_WINDOW_XDISPLAY(rootwin), dev);
for (ctr = 0, xic = xds->data; ctr < xds->num_classes; ctr++, xic += xic->length/2) {
if (xic->c_class == ButtonClass) {
xbs = (XButtonState*) xic;
}
}
if (!xbs) {
return true;
}
state = state << bit;
/* debug mouse state buttons
for (int ctr = 1; ctr < 10; ctr++) {
int byte = ctr / 8;
int bit = ctr % 8;
state = 1 << bit;
fprintf(stderr, "(%d/%d)", byte, bit);
fprintf(stderr, "b%d: %d -- ", ctr, (xbs->buttons[byte] & state) >> bit);
}
fprintf(stderr, "\n");
*/
if ((xbs->buttons[byte] & state) >> bit) {
ptt_on = true;
}
XFreeDeviceState(xds);
if (ptt_on) {
isTransmittingMouse = true;
startTransmit();
} else {
isTransmittingMouse = false;
if (! isTransmittingButton && ! isTransmittingKey && ! isTransmittingVA) {
stopTransmit();
}
}
return(true);
}/*}}}*/
bool Mangler::updateXferAmounts(void) {/*{{{*/
double bytes;
uint32_t packets;
char buf[1024];
builder->get_widget("sentLabel", label);
bytes = v3_get_bytes_sent();
packets = v3_get_packets_sent();
if (bytes > 1024*1024) {
snprintf(buf, 1023, "%2.2f megabytes / %u packets", bytes/1024/1024, packets);
} else if (bytes > 1024) {
snprintf(buf, 1023, "%2.2f kilobytes / %u packets", bytes/1024, packets);
} else if (bytes) {
snprintf(buf, 1023, "%.0f bytes / %u packets", bytes, packets);
} else {
snprintf(buf, 1023, "N/A");
}
label->set_text(buf);
builder->get_widget("recvLabel", label);
bytes = v3_get_bytes_recv();
packets = v3_get_packets_recv();
if (bytes > 1024*1024) {
snprintf(buf, 1023, "%2.2f megabytes / %u packets", bytes/1024/1024, packets);
} else if (bytes > 1024) {
snprintf(buf, 1023, "%2.2f kilobytes / %u packets", bytes/1024, packets);
} else if (bytes) {
snprintf(buf, 1023, "%.0f bytes / %u packets", bytes, packets);
} else {
snprintf(buf, 1023, "N/A");
}
label->set_text(buf);
return(true);
}/*}}}*/
/* {{{ GdkFilterReturn ptt_filter(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) {
GdkWindow *rootwin = gdk_get_default_root_window();
XEvent *xevent = (XEvent *)gdk_xevent;
if (! mangler) {
return GDK_FILTER_CONTINUE;
}
if (! mangler->settings->config.PushToTalkMouseEnabled) {
mangler->isTransmittingKey = false;
return GDK_FILTER_CONTINUE;
}
if (xevent->type == ButtonPress && !mangler->isTransmittingMouse && xevent->xbutton.button == mangler->settings->config.PushToTalkMouseValueInt) {
fprintf(stderr, "press\n");
mangler->startTransmit();
mangler->isTransmittingMouse = true;
fprintf(stderr, "allow\n");
XAllowEvents(GDK_WINDOW_XDISPLAY(rootwin), AsyncPointer, CurrentTime);
fprintf(stderr, "ungrab pointer\n");
XUngrabPointer(GDK_WINDOW_XDISPLAY(rootwin), CurrentTime);
fprintf(stderr, "ungrab button\n");
XUngrabButton(GDK_WINDOW_XDISPLAY(rootwin), mangler->settings->config.PushToTalkMouseValueInt, AnyModifier, GDK_ROOT_WINDOW());
fprintf(stderr, "grab button\n");
XGrabButton(GDK_WINDOW_XDISPLAY(rootwin), mangler->settings->config.PushToTalkMouseValueInt, AnyModifier, GDK_ROOT_WINDOW(), True, ButtonPressMask|ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None);
return GDK_FILTER_CONTINUE;
} else if ((xevent->type == ButtonRelease) && (xevent->xbutton.button == mangler->settings->config.PushToTalkMouseValueInt)) {
fprintf(stderr, "release\n");
mangler->stopTransmit();
mangler->isTransmittingMouse = false;
fprintf(stderr, "allow\n");
XAllowEvents(GDK_WINDOW_XDISPLAY(rootwin), AsyncPointer, CurrentTime);
fprintf(stderr, "ungrab pointer\n");
XUngrabPointer(GDK_WINDOW_XDISPLAY(rootwin), CurrentTime);
fprintf(stderr, "ungrab button\n");
XUngrabButton(GDK_WINDOW_XDISPLAY(rootwin), mangler->settings->config.PushToTalkMouseValueInt, AnyModifier, GDK_ROOT_WINDOW());
fprintf(stderr, "grab button\n");
XGrabButton(GDK_WINDOW_XDISPLAY(rootwin), mangler->settings->config.PushToTalkMouseValueInt, AnyModifier, GDK_ROOT_WINDOW(), True, ButtonPressMask|ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None);
return GDK_FILTER_CONTINUE;
}
return GDK_FILTER_CONTINUE;
} }}} */
bool Mangler::updateIntegration(void) {/*{{{*/
if (v3_is_loggedin()) {
if (! config["AudioIntegrationEnabled"].toBool() || integration->client == MusicClient_None) {
if (integration_text != "") {
integration_text = "";
v3_set_text(
(char *)ustring_to_c(comment).c_str(),
(char *)ustring_to_c(url).c_str(),
(char *)"",
true);
}
return true;
}
Glib::ustring formatted_text = integration->format();
switch (integration->get_mode()) {
// Polling (mpd)
case 0:
if ( ((integration->update(false) || !integration->first()) ) || integration_text != formatted_text ) {
integration_text = integration->format();
v3_set_text(
(char *)ustring_to_c(comment).c_str(),
(char *)ustring_to_c(url).c_str(),
(char *)ustring_to_c(integration_text).c_str(),
true);
}
break;
// Listening / callbacks (dbus ones)
case 1:
if (integration_text != formatted_text) {
integration_text = formatted_text;
v3_set_text(
(char *)ustring_to_c(comment).c_str(),
(char *)ustring_to_c(url).c_str(),
(char *)ustring_to_c(integration_text).c_str(),
true);
}
break;
}
}
return true;
}/*}}}*/
Glib::ustring Mangler::getPasswordEntry(Glib::ustring title, Glib::ustring prompt) {/*{{{*/
password = "";
passwordEntry->set_text("");
passwordDialog->set_keep_above(true);
passwordDialog->set_title(title);
passwordDialog->run();
passwordDialog->hide();
return(password);
}/*}}}*/
void Mangler::passwordDialogOkButton_clicked_cb(void) {/*{{{*/
password = passwordEntry->get_text();
}/*}}}*/
void Mangler::passwordDialogCancelButton_clicked_cb(void) {/*{{{*/
password = "";
}/*}}}*/
bool Mangler::getReasonEntry(Glib::ustring title, Glib::ustring prompt) {/*{{{*/
reason = "";
reasonValid = false;
reasonEntry->set_text("");
reasonDialog->set_keep_above(true);
reasonDialog->set_title(title);
reasonDialog->run();
reasonDialog->hide();
return reasonValid;
}/*}}}*/
void Mangler::reasonDialogOkButton_clicked_cb(void) {/*{{{*/
reason = reasonEntry->get_text();
reasonValid = true;
}/*}}}*/
void Mangler::reasonDialogCancelButton_clicked_cb(void) {/*{{{*/
reasonValid = false;
}/*}}}*/
void Mangler::textStringChangeDialogOkButton_clicked_cb(void) {/*{{{*/
comment = textStringChangeCommentEntry->get_text();
url = textStringChangeURLEntry->get_text();
integration_text = textStringChangeIntegrationEntry->get_text();
if (! connectedServerName.empty()) {
if (config.servers[connectedServerName]["PersistentComments"].toBool()) {
config.servers[connectedServerName]["Comment"] = comment;
config.servers.save();
}
}
v3_set_text(
(char *)ustring_to_c(comment).c_str(),
(char *)ustring_to_c(url).c_str(),
(char *)ustring_to_c(integration_text).c_str(),
textStringSilenceCommentCheckButton->get_active());
}/*}}}*/
void Mangler::textStringChangeDialogCancelButton_clicked_cb(void) {/*{{{*/
textStringChangeCommentEntry->set_text(comment);
textStringChangeURLEntry->set_text(url);
textStringChangeIntegrationEntry->set_text(integration_text);
}/*}}}*/
// Misc Functions
uint32_t Mangler::getActiveServer(void) {/*{{{*/
builder->get_widget("serverSelectComboBox", combobox);
return combobox->get_active_row_number();
}/*}}}*/
void Mangler::setActiveServer(uint32_t row_number) {/*{{{*/
builder->get_widget("serverSelectComboBox", combobox);
combobox->set_active(row_number);
}/*}}}*/
void Mangler::errorDialog(Glib::ustring message) {/*{{{*/
builder->get_widget("errorWindow", window);
window->set_keep_above(true);
window->set_icon(icons["tray_icon"]);
builder->get_widget("errorMessageLabel", label);
label->set_text(message);
window->show();
/*
builder->get_widget("errorDialog", msgdialog);
msgdialog->set_icon(icons["tray_icon"]);
msgdialog->set_keep_above(true);
msgdialog->set_message(message);
msgdialog->run();
msgdialog->hide();
*/
}/*}}}*/
void Mangler::errorOKButton_clicked_cb(void) {/*{{{*/
builder->get_widget("errorWindow", window);
window->hide();
}/*}}}*/
ManglerError::ManglerError(uint32_t code, Glib::ustring message, Glib::ustring module) {/*{{{*/
this->code = code;
this->message = message;
this->module = module;
}/*}}}*/
std::string Mangler::stripMotdRtf(const char *input) {/*{{{*/
// commentary by x87bliss (Russ Kubes) for your reading pleasure
std::string motd; // I use std::string since the RTF in the MOTDs is not unicode
if (!input || strlen(input) < 5 || memcmp("{\\rtf", input, 5) != 0) { // if the motd is not RTF
motd = input;
return motd;
}
// Note this function only strips RTF markup to make RTF MOTDs human readable. It doesn't support any advanced interpretation of RTF markup.
size_t inputlen = strlen(input);
motd.reserve(inputlen); // allocate enough space, the resulting string will be smaller than input length
// rtf_status is what is the loop looking at, i.e. do we need to interpret controls
enum {RTF_TEXT, RTF_CONTROL, RTF_CONTROL_END, RTF_IGNORE, RTF_BIN} rtf_status = RTF_TEXT;
size_t ignorecount; // number of closing braces to ignore for "\*"
size_t controlpos; // stores the position of the first character of a control word
for (size_t pos = 0; pos < inputlen; ++pos) {
if (rtf_status == RTF_IGNORE) {
if (inputlen - pos > 4 && memcmp("\\bin", input + pos, 4) == 0 && input[pos + 4] >= '0' && input[pos + 4] <= '9') {
// Encountered some binary data that we have to ignore. We have to ignore this a special way since the data may contain special characters
pos += 4;
size_t binskip = 0; // how much data to skip
for (; input[pos] >= '0' && input[pos] <= '9'; ++pos) {
binskip = (binskip * 10) + (input[pos] - '0');
}
pos += binskip;
continue; // every \binN has a space between it and its binary data, continue skips that too.
}
if (input[pos] == '{') {
++ignorecount;
}
if (input[pos] == '}' && --ignorecount == 0) {
rtf_status = RTF_TEXT; // we can stop ignoring now
}
continue; // still ignoring, or ignore the ending brace;
}
if (rtf_status == RTF_CONTROL) {
if ((input[pos] >= 'a' && input[pos] <= 'z') || // valid characters in a control word are a-z, A-Z, 0-9, and - (for negative numbers)
(input[pos] >= 'A' && input[pos] <= 'Z') ||
(input[pos] >= '0' && input[pos] <= '9') ||
(input[pos] == '\'' && pos == controlpos) || // apostrophe is valid, but only as the first character of a control word
input[pos] == '-') {
continue;
} else {
rtf_status = RTF_CONTROL_END; // Any control word has ended
}
}
if (rtf_status == RTF_CONTROL_END) {
// note all RTF control words are case-sensitive. So memcmp can be used instead of stricmp
size_t controllen = pos - controlpos;
// check all exact matches first
if (controllen == 3 && input[controlpos] == '\'') { // 8-bit hex character
char hh = -1, h; // hh is the full interpreted hex character, h is a working value for each hex digit
h = input[controlpos + 1];
if (h >= '0' && h <= '9') {
hh = h - '0'; // temporarily store the value and check for errors in the second digit
} else if (h >= 'a' && h <= 'f') {
hh = h - 'a' + 10;
} else if (h >= 'A' && h <= 'F') {
hh = h - 'A' + 10; // technically only lowercase letters are supported by RTF
}
h = input[controlpos + 2];
if (h >= '0' && h <= '9') {
h = h - '0'; // temporarily store the value
} else if (h >= 'a' && h <= 'f') {
h = h - 'a' + 10;
} else if (h >= 'A' && h <= 'F') {
h = h - 'A' + 10; // technically only lowercase letters are supported by RTF
} else {
h = -1;
}
if (hh >= 0 && h >= 0) { // both hex digits were valid
hh = (hh * 16) + h; // convert each value to the whole character
motd.append(1, hh);
}
} else if (controllen == 3 && memcmp("tab", input + controlpos, 3) == 0) {
motd.append(1, '\t'); // in case Mangler's motd window doesn't properly handle tabs, this can be changed to (4, ' ') for 4 spaces
} else if (controllen == 3 && memcmp("par", input + controlpos, 3) == 0) {
motd.append("\r\n");
} else if (controllen == 4 && (memcmp("line", input + controlpos, 4) == 0 ||
memcmp("page", input + controlpos, 4) == 0 || memcmp("sect", input + controlpos, 4) == 0)) {
motd.append("\r\n");
} else if (controllen == 7 && (memcmp("fonttbl", input + controlpos, 7) == 0 || // nonvisible formatting table
memcmp("filetbl", input + controlpos, 4) == 0)) { // sub-documents table
ignorecount = 1;
rtf_status = RTF_IGNORE; // we're going to ignore a table
} else if (controllen == 8 && memcmp("colortbl", input + controlpos, 8) == 0) { // nonvisible formatting table
ignorecount = 1;
rtf_status = RTF_IGNORE; // we're going to ignore a table
} else if (controllen == 10 && (memcmp("stylesheet", input + controlpos, 10) == 0 || // nonvisible formatting table
memcmp("listtables", input + controlpos, 10) == 0)) { // stores formatting information for lists
ignorecount = 1;
rtf_status = RTF_IGNORE; // we're going to ignore a table
} else if (controllen == 6 && memcmp("revtbl", input + controlpos, 6) == 0) { // This table contains nonvisible information about revisions
ignorecount = 1;
rtf_status = RTF_IGNORE; // we're going to ignore a table
} else if (controllen == 4 && memcmp("info", input + controlpos, 4) == 0) { // The info table contains nonvisible metadata, like author etc..
ignorecount = 1;
rtf_status = RTF_IGNORE; // we're going to ignore a table
} else if (controllen > 3 && memcmp("bin", input + controlpos, 3) == 0 && input[controlpos + 3] >= '0' && input[controlpos + 3] <= '9') {
// Now start to look for partial matches
// We encountered some binary data that we need to skip
size_t binskip = 0; // how much data to skip
for (size_t bpos = controlpos + 3; input[bpos] >= '0' && input [bpos] <= '9'; ++bpos) {
binskip = (binskip * 10) + (input[bpos] - '0');
}
pos += binskip;
rtf_status = RTF_TEXT;
continue;
}
if (input[pos] != ' ') {
--pos; // we need to reevaluate the delimiter if it wasn't a space
}
if (rtf_status != RTF_IGNORE) {
rtf_status = RTF_TEXT;
}
continue;
}
if (rtf_status == RTF_TEXT) {
if (input[pos] == '\\') {
// First check for "\{", "\}", "\\" and "\*", which each would break this function if not explicitly looked for right away
if (inputlen - pos < 2) {
break; // we need at least 2 characters, probably a malformed RTF message.
}
++pos; // increment it here once, so we don't have to add one for each check
if (input[pos] == '{' || input[pos] == '}' || input[pos] == '\\') {
motd.append(1, input[pos]);
continue;
} else if (input[pos] == '*') {
ignorecount = 1;
rtf_status = RTF_IGNORE;
continue;
} else {
controlpos = pos--; // the control word starts at the incremented pos, but we need to decrement it again to examine it
rtf_status = RTF_CONTROL;
continue;
}
} else if (input[pos] != '{' && input[pos] != '}' && // we're just ignoring groups since we're not formatting
input[pos] != '\r' && input[pos] != '\n') { // ignore CRs and LFs in the RTF text
motd.append(1, input[pos]);
}
}
}
return motd;
}/*}}}*/
int
main(int argc, char **argv) {
Gtk::Main kit(argc, argv);
struct _cli_options options = { 0 };
char *locale;
extern char *optarg;
int opt;
while ((opt = getopt(argc, argv, "hd:s:u:p:")) != -1) {
switch (opt) {
case 'h':
fprintf(stderr, "%s: optional arguments: -d .ui -s hostname:port -u username -p password\n", argv[0]);
exit(EXIT_FAILURE);
case 'd':
options.uifilename = c_to_ustring(optarg);
options.uifromfile = true;
fprintf(stderr, "using ui definition file: %s\n", optarg);
break;
case 's':
options.qc_server = c_to_ustring(optarg);
break;
case 'u':
options.qc_username = c_to_ustring(optarg);
break;
case 'p':
options.qc_password = c_to_ustring(optarg);
break;
}
}
if (!(locale = setlocale(LC_ALL, ""))) {
fprintf(stderr, "Can't set the specified locale! " "Check LANG, LC_CTYPE, LC_ALL.\n");
exit(EXIT_FAILURE);
}
//fprintf(stderr, "initialized locale: %s\n", locale);
if (!Glib::thread_supported()) {
Glib::thread_init();
}
gdk_threads_init();
mangler = new Mangler(&options);
gdk_threads_enter();
Gtk::Main::run(*mangler->manglerWindow);
gdk_threads_leave();
delete mangler;
exit(EXIT_SUCCESS);
return 0;
}
mangler-1.2.5/src/._mangler.cpp 0000644 0000765 0000062 00000000336 11602153752 014251 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/mangler.1 0000644 0000765 0000062 00000001452 12075416741 013417 0 ustar staff .TH MANGLER "1" "January 2013" "mangler 1.2.5"
.SH NAME
mangler \- a Ventrilo compatible client for Linux
.SH SYNOPSIS
.B mangler
[\fB\-s\fR \fIhostname:port\fR]
[\fB\-u\fR \fIusername\fR]
[\fB\-p\fR \fIpassword\fR]
.SH DESCRIPTION
\fBmangler\fR is an open source VOIP client capable of connecting to
Ventrilo 3.x servers. It is capable of performing almost all standard user
functionality found in a Windows Ventrilo client.
.PP
.SH OPTIONS
.TP
\fB\-s\fR \fIhostname:port\fR
Specify hostname and port of the server for Mangler to connect to.
.TP
\fB\-u\fR \fIusername\fR
Specify username for Mangler to use.
.TP
\fB\-p\fR \fIpassword\fR
Specify password for Mangler to use.
.SH AUTHOR
This manual page was written by Vincent Cheng ,
for the Debian project (and may be used by others).
mangler-1.2.5/src/._mangler.1 0000644 0000765 0000062 00000000336 12075416741 013634 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/Makefile.in 0000644 0000765 0000062 00000067316 12075416741 013770 0 ustar staff # Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__make_dryrun = \
{ \
am__dry=no; \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
*) \
for am__flg in $$MAKEFLAGS; do \
case $$am__flg in \
*=*|--*) ;; \
*n*) am__dry=yes; break;; \
esac; \
done;; \
esac; \
test $$am__dry = yes; \
}
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = mangler$(EXEEXT)
subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pthread.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \
"$(DESTDIR)$(desktopdir)" "$(DESTDIR)$(icondir)"
PROGRAMS = $(bin_PROGRAMS)
am_mangler_OBJECTS = mangler.$(OBJEXT) channeltree.$(OBJEXT) \
mangleraudio.$(OBJEXT) manglerbackend.$(OBJEXT) \
manglerpulse.$(OBJEXT) mangleralsa.$(OBJEXT) \
mangleross.$(OBJEXT) manglernetwork.$(OBJEXT) \
manglerserverlist.$(OBJEXT) manglersettings.$(OBJEXT) \
manglerconfig.$(OBJEXT) manglerchat.$(OBJEXT) \
manglerprivchat.$(OBJEXT) manglercharset.$(OBJEXT) \
manglerintegration.$(OBJEXT) mangleradmin.$(OBJEXT) \
manglerrecorder.$(OBJEXT) manglerosd.$(OBJEXT) \
manglerg15.$(OBJEXT) inilib.$(OBJEXT)
mangler_OBJECTS = $(am_mangler_OBJECTS)
am__DEPENDENCIES_1 =
mangler_DEPENDENCIES = @top_srcdir@/libventrilo3/libventrilo3.la \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(mangler_SOURCES)
DIST_SOURCES = $(mangler_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
man1dir = $(mandir)/man1
NROFF = nroff
MANS = $(man_MANS)
DATA = $(desktop_DATA) $(icon_DATA)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GLIB_CFLAGS = @GLIB_CFLAGS@
GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
GLIB_LIBS = @GLIB_LIBS@
GLIB_MKENUMS = @GLIB_MKENUMS@
GOBJECT_QUERY = @GOBJECT_QUERY@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_LIBS = @PTHREAD_LIBS@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
SUBDIR_LIST = @SUBDIR_LIST@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
alsa_CFLAGS = @alsa_CFLAGS@
alsa_LIBS = @alsa_LIBS@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
ax_pthread_config = @ax_pthread_config@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
dbus_CFLAGS = @dbus_CFLAGS@
dbus_LIBS = @dbus_LIBS@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
gthread_CFLAGS = @gthread_CFLAGS@
gthread_LIBS = @gthread_LIBS@
gtk_CFLAGS = @gtk_CFLAGS@
gtk_LIBS = @gtk_LIBS@
gtkmm_CFLAGS = @gtkmm_CFLAGS@
gtkmm_LIBS = @gtkmm_LIBS@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
opus_CFLAGS = @opus_CFLAGS@
opus_LIBS = @opus_LIBS@
oss_CFLAGS = @oss_CFLAGS@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
pulse_CFLAGS = @pulse_CFLAGS@
pulse_LIBS = @pulse_LIBS@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
speex_CFLAGS = @speex_CFLAGS@
speex_LIBS = @speex_LIBS@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
x11_CFLAGS = @x11_CFLAGS@
x11_LIBS = @x11_LIBS@
xi_CFLAGS = @xi_CFLAGS@
xi_LIBS = @xi_LIBS@
ACLOCAL_AMFLAGS = -I m4
icondir = $(datadir)/pixmaps
desktopdir = $(datadir)/applications
icon_DATA = ../icons/mangler_logo.svg
desktop_DATA = ../mangler.desktop
man_MANS = mangler.1
mangler_SOURCES = \
manglerui.h \
mangler.cpp mangler.h \
channeltree.cpp channeltree.h \
mangleraudio.cpp mangleraudio.h \
manglerbackend.cpp manglerbackend.h \
manglerpulse.cpp manglerpulse.h \
mangleralsa.cpp mangleralsa.h \
mangleross.cpp mangleross.h \
manglernetwork.cpp manglernetwork.h \
manglerserverlist.cpp manglerserverlist.h \
manglersettings.cpp manglersettings.h \
manglerconfig.cpp manglerconfig.h \
manglerchat.cpp manglerchat.h \
manglerprivchat.cpp manglerprivchat.h \
manglercharset.cpp manglercharset.h \
manglerintegration.cpp manglerintegration.h \
mangleradmin.cpp mangleradmin.h \
manglerrecorder.cpp manglerrecorder.h \
manglerosd.cpp manglerosd.h \
manglerg15.cpp manglerg15.h \
inilib.cpp inilib.h
mangler_LDADD = @top_srcdir@/libventrilo3/libventrilo3.la $(gtkmm_LIBS) $(gthread_LIBS) $(pulse_LIBS) $(alsa_LIBS) $(dbus_LIBS) $(xi_LIBS) $(x11_LIBS)
INCLUDES = -I@top_srcdir@/libventrilo3/ -I@top_srcdir@/icons/ -I@top_srcdir@/sounds/ $(gtkmm_CFLAGS) $(gthread_CFLAGS) $(pulse_CFLAGS) $(alsa_CFLAGS) $(oss_CFLAGS) $(dbus_CFLAGS) $(xi_CFLAGS) $(x11_CFLAGS)
all: all-am
.SUFFIXES:
.SUFFIXES: .cpp .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu src/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
} \
; done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && rm -f $$files
clean-binPROGRAMS:
@list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
echo " rm -f" $$list; \
rm -f $$list || exit $$?; \
test -n "$(EXEEXT)" || exit 0; \
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
mangler$(EXEEXT): $(mangler_OBJECTS) $(mangler_DEPENDENCIES) $(EXTRA_mangler_DEPENDENCIES)
@rm -f mangler$(EXEEXT)
$(CXXLINK) $(mangler_OBJECTS) $(mangler_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channeltree.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inilib.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mangler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mangleradmin.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mangleralsa.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mangleraudio.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglerbackend.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglercharset.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglerchat.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglerconfig.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglerg15.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglerintegration.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglernetwork.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglerosd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mangleross.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglerprivchat.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglerpulse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglerrecorder.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglerserverlist.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manglersettings.Po@am__quote@
.cpp.o:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
.cpp.obj:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.cpp.lo:
@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
install-man1: $(man_MANS)
@$(NORMAL_INSTALL)
@list1=''; \
list2='$(man_MANS)'; \
test -n "$(man1dir)" \
&& test -n "`echo $$list1$$list2`" \
|| exit 0; \
echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
$(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
{ for i in $$list1; do echo "$$i"; done; \
if test -n "$$list2"; then \
for i in $$list2; do echo "$$i"; done \
| sed -n '/\.1[a-z]*$$/p'; \
fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
done | \
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
sed 'N;N;s,\n, ,g' | { \
list=; while read file base inst; do \
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
fi; \
done; \
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
while read files; do \
test -z "$$files" || { \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
done; }
uninstall-man1:
@$(NORMAL_UNINSTALL)
@list=''; test -n "$(man1dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
sed -n '/\.1[a-z]*$$/p'; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
install-desktopDATA: $(desktop_DATA)
@$(NORMAL_INSTALL)
@list='$(desktop_DATA)'; test -n "$(desktopdir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(desktopdir)'"; \
$(MKDIR_P) "$(DESTDIR)$(desktopdir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(desktopdir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(desktopdir)" || exit $$?; \
done
uninstall-desktopDATA:
@$(NORMAL_UNINSTALL)
@list='$(desktop_DATA)'; test -n "$(desktopdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(desktopdir)'; $(am__uninstall_files_from_dir)
install-iconDATA: $(icon_DATA)
@$(NORMAL_INSTALL)
@list='$(icon_DATA)'; test -n "$(icondir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(icondir)'"; \
$(MKDIR_P) "$(DESTDIR)$(icondir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(icondir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(icondir)" || exit $$?; \
done
uninstall-iconDATA:
@$(NORMAL_UNINSTALL)
@list='$(icon_DATA)'; test -n "$(icondir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(icondir)'; $(am__uninstall_files_from_dir)
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@list='$(MANS)'; if test -n "$$list"; then \
list=`for p in $$list; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
if test -n "$$list" && \
grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
echo " typically \`make maintainer-clean' will remove them" >&2; \
exit 1; \
else :; fi; \
else :; fi
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS) $(MANS) $(DATA)
installdirs:
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(desktopdir)" "$(DESTDIR)$(icondir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-desktopDATA install-iconDATA install-man
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-binPROGRAMS
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man: install-man1
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-desktopDATA \
uninstall-iconDATA uninstall-man
uninstall-man: uninstall-man1
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
clean-generic clean-libtool ctags distclean distclean-compile \
distclean-generic distclean-libtool distclean-tags distdir dvi \
dvi-am html html-am info info-am install install-am \
install-binPROGRAMS install-data install-data-am \
install-desktopDATA install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-iconDATA \
install-info install-info-am install-man install-man1 \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags uninstall uninstall-am \
uninstall-binPROGRAMS uninstall-desktopDATA uninstall-iconDATA \
uninstall-man uninstall-man1
manglerui:
echo -n "char ManglerUI[] = " > manglerui.h
cat mangler.ui | sed 's/"/\\"/g' | sed 's/^/"/' | sed 's/$$/\\n"/' >> manglerui.h
echo ";" >> manglerui.h
dev:
cd ../libventrilo3 && make dev
g++ -g -Wall -Wextra -o mangler -I../ -I../libventrilo3/ -I../icons/ -I../sounds/ -pthread \
mangler.cpp channeltree.cpp mangleraudio.cpp \
manglerbackend.cpp manglerpulse.cpp mangleralsa.cpp mangleross.cpp \
manglernetwork.cpp manglerserverlist.cpp manglersettings.cpp manglerconfig.cpp \
manglerchat.cpp manglerprivchat.cpp manglercharset.cpp manglerintegration.cpp \
mangleradmin.cpp manglerrecorder.cpp manglerosd.cpp manglerg15.cpp \
inilib.cpp ../libventrilo3/libventrilo3.a \
$(pulse_LIBS) $(alsa_LIBS) $(speex_LIBS) $(opus_LIBS) $(LIBS) \
`pkg-config --cflags --libs dbus-glib-1` \
`pkg-config --cflags --libs gthread-2.0` \
`pkg-config --cflags --libs gtkmm-2.4`
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
mangler-1.2.5/src/._Makefile.in 0000644 0000765 0000062 00000000336 12075416741 014172 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/Makefile.am 0000644 0000765 0000062 00000004265 11757473612 013757 0 ustar staff
ACLOCAL_AMFLAGS = -I m4
icondir = $(datadir)/pixmaps
desktopdir = $(datadir)/applications
manglerui:
echo -n "char ManglerUI[] = " > manglerui.h
cat mangler.ui | sed 's/"/\\"/g' | sed 's/^/"/' | sed 's/$$/\\n"/' >> manglerui.h
echo ";" >> manglerui.h
bin_PROGRAMS = mangler
icon_DATA = ../icons/mangler_logo.svg
desktop_DATA = ../mangler.desktop
man_MANS = mangler.1
mangler_SOURCES = \
manglerui.h \
mangler.cpp mangler.h \
channeltree.cpp channeltree.h \
mangleraudio.cpp mangleraudio.h \
manglerbackend.cpp manglerbackend.h \
manglerpulse.cpp manglerpulse.h \
mangleralsa.cpp mangleralsa.h \
mangleross.cpp mangleross.h \
manglernetwork.cpp manglernetwork.h \
manglerserverlist.cpp manglerserverlist.h \
manglersettings.cpp manglersettings.h \
manglerconfig.cpp manglerconfig.h \
manglerchat.cpp manglerchat.h \
manglerprivchat.cpp manglerprivchat.h \
manglercharset.cpp manglercharset.h \
manglerintegration.cpp manglerintegration.h \
mangleradmin.cpp mangleradmin.h \
manglerrecorder.cpp manglerrecorder.h \
manglerosd.cpp manglerosd.h \
manglerg15.cpp manglerg15.h \
inilib.cpp inilib.h
mangler_LDADD = @top_srcdir@/libventrilo3/libventrilo3.la $(gtkmm_LIBS) $(gthread_LIBS) $(pulse_LIBS) $(alsa_LIBS) $(dbus_LIBS) $(xi_LIBS) $(x11_LIBS)
INCLUDES = -I@top_srcdir@/libventrilo3/ -I@top_srcdir@/icons/ -I@top_srcdir@/sounds/ $(gtkmm_CFLAGS) $(gthread_CFLAGS) $(pulse_CFLAGS) $(alsa_CFLAGS) $(oss_CFLAGS) $(dbus_CFLAGS) $(xi_CFLAGS) $(x11_CFLAGS)
dev:
cd ../libventrilo3 && make dev
g++ -g -Wall -Wextra -o mangler -I../ -I../libventrilo3/ -I../icons/ -I../sounds/ -pthread \
mangler.cpp channeltree.cpp mangleraudio.cpp \
manglerbackend.cpp manglerpulse.cpp mangleralsa.cpp mangleross.cpp \
manglernetwork.cpp manglerserverlist.cpp manglersettings.cpp manglerconfig.cpp \
manglerchat.cpp manglerprivchat.cpp manglercharset.cpp manglerintegration.cpp \
mangleradmin.cpp manglerrecorder.cpp manglerosd.cpp manglerg15.cpp \
inilib.cpp ../libventrilo3/libventrilo3.a \
$(pulse_LIBS) $(alsa_LIBS) $(speex_LIBS) $(opus_LIBS) $(LIBS) \
`pkg-config --cflags --libs dbus-glib-1` \
`pkg-config --cflags --libs gthread-2.0` \
`pkg-config --cflags --libs gtkmm-2.4`
mangler-1.2.5/src/._Makefile.am 0000644 0000765 0000062 00000000336 11757473612 014167 0 ustar staff Mac OS X 2 ¬ Þ ATTR Þ ˜ F ˜ F com.apple.quarantine q/0001;50f61d53;Google\x20Chrome;BCF5BAC9-6A67-4B7E-BA13-466EF0412B47 mangler-1.2.5/src/inilib.h 0000644 0000765 0000062 00000010664 11602153752 013327 0 ustar staff /*
* vim: softtabstop=4 shiftwidth=4 cindent foldmethod=marker expandtab
*
* $LastChangedDate: 2011-06-27 21:20:10 +0200 (Mon, 27 Jun 2011) $
* $Revision: 1139 $
* $LastChangedBy: econnell $
* $URL: http://svn.mangler.org/mangler/trunk/src/inilib.h $
*
* Copyright 2010-2011 Bob Shaffer II
*
* This file is part of Mangler.
*
* Mangler 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 3 of the License, or
* (at your option) any later version.
*
* Mangler 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 Mangler. If not, see .
*/
#ifndef INILIB_H_INCLUDED
#define INILIB_H_INCLUDED
#include
#include