|
|
@ -26,6 +26,8 @@ |
|
|
|
|
|
|
|
#include <unistd.h> |
|
|
|
#include <limits.h> |
|
|
|
#include <getopt.h> |
|
|
|
#include <stdarg.h> |
|
|
|
|
|
|
|
#include <globals.h> |
|
|
|
#include "scontrol.h" |
|
|
@ -132,111 +134,21 @@ static const char *amixer_warning_message = "\n\ |
|
|
|
Another instance of amixer-gtk \n\ |
|
|
|
is already running.\n"; |
|
|
|
|
|
|
|
static |
|
|
|
void signal_handler(int signum) |
|
|
|
{ |
|
|
|
switch(signum) { |
|
|
|
|
|
|
|
case SIGALRM: |
|
|
|
break; |
|
|
|
|
|
|
|
case SIGHUP: |
|
|
|
break; |
|
|
|
|
|
|
|
case SIGUSR1: |
|
|
|
break; |
|
|
|
|
|
|
|
switch(signum) { |
|
|
|
case SIGTERM: |
|
|
|
case SIGINT: |
|
|
|
case SIGQUIT: |
|
|
|
{ |
|
|
|
ui_delete(); |
|
|
|
} |
|
|
|
|
|
|
|
ui_delete(); |
|
|
|
exit(EXIT_SUCCESS); /* exit gracefully. */ |
|
|
|
break; |
|
|
|
|
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
class CmdArgParser : public Glib::OptionGroup |
|
|
|
{ |
|
|
|
public: |
|
|
|
CmdArgParser(const std::string&, const std::string&, const std::string&); |
|
|
|
|
|
|
|
private: |
|
|
|
void on_error(Glib::OptionContext& context, const Glib::Error& error); |
|
|
|
|
|
|
|
bool on_option_arg_filename( |
|
|
|
const Glib::ustring& option_name, const std::string& value, bool has_value); |
|
|
|
|
|
|
|
public: |
|
|
|
int m_card; |
|
|
|
std::string m_device; |
|
|
|
bool m_systray; |
|
|
|
int m_pid = 0; |
|
|
|
int x_pos = 1500; |
|
|
|
int y_pos = 0; |
|
|
|
int width = 850; |
|
|
|
int height = 480; |
|
|
|
bool m_hidden = true; |
|
|
|
}; |
|
|
|
|
|
|
|
CmdArgParser::CmdArgParser(const std::string& dsc1, const std::string& dsc2, const std::string& dsc3) |
|
|
|
: Glib::OptionGroup{dsc1, dsc2, dsc3}, |
|
|
|
m_device(""), |
|
|
|
m_card(-1), |
|
|
|
m_systray(false) |
|
|
|
{ |
|
|
|
Glib::OptionEntry optDevice; |
|
|
|
optDevice.set_long_name("device"); |
|
|
|
optDevice.set_short_name('D'); |
|
|
|
optDevice.set_description(dsc1); |
|
|
|
add_entry_filename(optDevice, m_device); |
|
|
|
|
|
|
|
Glib::OptionEntry optCard; |
|
|
|
optCard.set_long_name("card"); |
|
|
|
optCard.set_short_name('c'); |
|
|
|
optCard.set_description(dsc2); |
|
|
|
add_entry(optCard, m_card); |
|
|
|
|
|
|
|
Glib::OptionEntry optSystray; |
|
|
|
optSystray.set_long_name("systray"); |
|
|
|
optSystray.set_description(dsc3); |
|
|
|
add_entry(optSystray, m_systray); |
|
|
|
|
|
|
|
Glib::OptionEntry optX; |
|
|
|
optX.set_long_name("xpos"); |
|
|
|
optX.set_short_name('x'); |
|
|
|
add_entry(optX, x_pos); |
|
|
|
|
|
|
|
Glib::OptionEntry optY; |
|
|
|
optY.set_long_name("ypos"); |
|
|
|
optY.set_short_name('y'); |
|
|
|
add_entry(optY, y_pos); |
|
|
|
|
|
|
|
Glib::OptionEntry optW; |
|
|
|
optW.set_long_name("width"); |
|
|
|
optW.set_short_name('W'); |
|
|
|
add_entry(optW, width); |
|
|
|
|
|
|
|
Glib::OptionEntry optH; |
|
|
|
optH.set_long_name("height"); |
|
|
|
optH.set_short_name('H'); |
|
|
|
add_entry(optH, height); |
|
|
|
|
|
|
|
Glib::OptionEntry optHidden; |
|
|
|
optHidden.set_long_name("hidden"); |
|
|
|
add_entry(optHidden, m_hidden); |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
CmdArgParser::on_error(Glib::OptionContext& /* context */, const Glib::Error& /* error */) |
|
|
|
{ |
|
|
|
std::cout << "on_error called" << std::endl; |
|
|
|
} |
|
|
|
|
|
|
|
static |
|
|
|
bool CheckForAnotherInstance(const char *filename) |
|
|
|
{ |
|
|
@ -291,10 +203,28 @@ bool CheckForAnotherInstance(const char *filename) |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// print usage statement
|
|
|
|
static |
|
|
|
void config_usage(const char *progname) |
|
|
|
{ |
|
|
|
fprintf(stderr, "%s -- Amixer-gtk\n\n" |
|
|
|
"Usage: %s [options]\n\n" |
|
|
|
"Options:\n" |
|
|
|
" -h --help this help\n" |
|
|
|
" -c --card N select the hw:N card" |
|
|
|
" -D --device select the device, default 'default'\n" |
|
|
|
" -s --systray run in the systray\n" |
|
|
|
" -x --xpos x position\n" |
|
|
|
" -y --ypos y position\n" |
|
|
|
" -W --width window width\n" |
|
|
|
" -H --height window height\n" |
|
|
|
" -i --hide hide the window\n\n", |
|
|
|
progname, progname); |
|
|
|
} |
|
|
|
|
|
|
|
int main(int argc, char *argv[]) |
|
|
|
{ |
|
|
|
unsigned int n, m; |
|
|
|
char *buf = nullptr; |
|
|
|
std::string snd_card; |
|
|
|
snd_pcm_t *pcm_handle = NULL; |
|
|
|
std::vector<AMixer::SControl *> scontents; |
|
|
@ -302,6 +232,14 @@ int main(int argc, char *argv[]) |
|
|
|
char lockfile[128]={0}; |
|
|
|
bool is_already_running; |
|
|
|
char target[PATH_MAX]={0}; |
|
|
|
|
|
|
|
char *buf = nullptr; |
|
|
|
bool m_systray = false; |
|
|
|
int x_pos = 1500; |
|
|
|
int y_pos = 0; |
|
|
|
int width = 850; |
|
|
|
int height = 480; |
|
|
|
int m_hidden = 0; |
|
|
|
|
|
|
|
std::string filename = "/proc/" + std::to_string(getpid()) + "/exe"; |
|
|
|
ssize_t len = ::readlink(filename.c_str(), target, sizeof(target)-1); |
|
|
@ -336,73 +274,110 @@ int main(int argc, char *argv[]) |
|
|
|
gtk_widget_destroy(dialog); |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
} |
|
|
|
|
|
|
|
std::signal(SIGTERM, signal_handler); |
|
|
|
std::signal(SIGINT, signal_handler); |
|
|
|
std::signal(SIGQUIT, signal_handler); |
|
|
|
|
|
|
|
// Parse command line arguments and retrieve values:
|
|
|
|
Glib::init(); |
|
|
|
setlocale(LC_ALL, ""); |
|
|
|
Glib::OptionContext context; |
|
|
|
|
|
|
|
CmdArgParser parser{ |
|
|
|
"Select the device", |
|
|
|
"Select the card", |
|
|
|
"Send to the system tray" |
|
|
|
}; |
|
|
|
|
|
|
|
context.set_main_group(parser); |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
context.parse(argc, argv); |
|
|
|
} |
|
|
|
catch (const Glib::Error& ex) |
|
|
|
{ |
|
|
|
std::cout << "Exception: " << ex.what() << std::endl; |
|
|
|
} |
|
|
|
|
|
|
|
std::cout << "parsed values: " << std::endl |
|
|
|
<< " device = " << parser.m_device << std::endl |
|
|
|
<< " card = " << parser.m_card << std::endl |
|
|
|
<< " systray = " << (parser.m_systray ? "enabled" : "disabled") << std::endl |
|
|
|
<< std::endl; |
|
|
|
|
|
|
|
if( !parser.m_device.empty() && parser.m_card != -1 ) { |
|
|
|
|
|
|
|
const char *p[] = { "amixer", "-D", parser.m_device.c_str(), "-c", std::to_string(parser.m_card).c_str(), (char*)0 }; |
|
|
|
n = sizeof(p)/sizeof(char*) - 1; |
|
|
|
get_snd_card( n, p, &buf); |
|
|
|
snd_card = std::string(buf); |
|
|
|
free(buf); |
|
|
|
static const struct option long_option[] = |
|
|
|
{ |
|
|
|
{"card", required_argument, 0, 'c'}, |
|
|
|
{"device", required_argument, 0, 'D'}, |
|
|
|
{"systray", no_argument, 0, 's'}, |
|
|
|
{"xpos", required_argument, 0, 'x'}, |
|
|
|
{"ypos", required_argument, 0, 'y'}, |
|
|
|
{"width", required_argument, 0, 'W'}, |
|
|
|
{"height", required_argument, 0, 'H'}, |
|
|
|
{"hide", required_argument, 0, 'i'}, |
|
|
|
{"help", no_argument, 0, 'h'}, |
|
|
|
{0, 0, 0, 0 }, |
|
|
|
}; |
|
|
|
|
|
|
|
} else if ( parser.m_device.empty() && parser.m_card != -1 ) { |
|
|
|
|
|
|
|
const char *p[] = { "amixer", "-c", std::to_string(parser.m_card).c_str(), (char*)0 }; |
|
|
|
n = sizeof(p)/sizeof(char*) - 1; |
|
|
|
get_snd_card( n, p, &buf); |
|
|
|
snd_card = std::string(buf); |
|
|
|
free(buf); |
|
|
|
buf = (char*)malloc(sizeof(char) * 64); |
|
|
|
if (!buf) { |
|
|
|
fprintf(stderr, "Memory allocation failure\n"); |
|
|
|
exit (EXIT_FAILURE); |
|
|
|
} |
|
|
|
|
|
|
|
memset(buf, 0, sizeof(buf)); |
|
|
|
|
|
|
|
while (1) { |
|
|
|
int c; |
|
|
|
int option_index = 0; |
|
|
|
|
|
|
|
if ((c = getopt_long(argc, argv, "c:D:sx:y:W:H:i:h", long_option, &option_index)) < 0) |
|
|
|
break; |
|
|
|
|
|
|
|
switch (c) { |
|
|
|
|
|
|
|
} else { |
|
|
|
case 's': |
|
|
|
m_systray = true; |
|
|
|
m_hidden = 1; |
|
|
|
break; |
|
|
|
case 'i': |
|
|
|
m_hidden = atoi(optarg); |
|
|
|
break; |
|
|
|
case 'c': |
|
|
|
{ |
|
|
|
int i; |
|
|
|
i = snd_card_get_index(optarg); |
|
|
|
if (i >= 0 && i < 32) |
|
|
|
sprintf(buf, "hw:%i", i); |
|
|
|
else { |
|
|
|
fprintf(stderr, "Invalid card number.\n"); |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
case 'D': |
|
|
|
{ |
|
|
|
char tmp[64]; |
|
|
|
strncpy(tmp, optarg, sizeof(tmp)-1); |
|
|
|
tmp[sizeof(tmp)-1] = '\0'; |
|
|
|
sprintf(buf, "%s", tmp); |
|
|
|
} |
|
|
|
break; |
|
|
|
case 'x': |
|
|
|
x_pos = atoi(optarg); |
|
|
|
break; |
|
|
|
case 'y': |
|
|
|
y_pos = atoi(optarg); |
|
|
|
break; |
|
|
|
case 'W': |
|
|
|
width = atoi(optarg); |
|
|
|
break; |
|
|
|
case 'H': |
|
|
|
height = atoi(optarg); |
|
|
|
break; |
|
|
|
case 'h': |
|
|
|
config_usage(progname.c_str()); |
|
|
|
break; |
|
|
|
case '?': |
|
|
|
if (isprint (optopt)) |
|
|
|
fprintf (stderr, "Unknown option `-%c'.\n", optopt); |
|
|
|
else |
|
|
|
fprintf (stderr, "Unknown option character `\\x%x'.\n", |
|
|
|
optopt); |
|
|
|
return 1; |
|
|
|
default: |
|
|
|
abort (); |
|
|
|
|
|
|
|
} // switch
|
|
|
|
} // while
|
|
|
|
|
|
|
|
if(*buf != 0) { |
|
|
|
|
|
|
|
snd_card = std::string(buf); |
|
|
|
|
|
|
|
} else { |
|
|
|
int err; |
|
|
|
snd_pcm_t *pcm_handle = NULL; |
|
|
|
|
|
|
|
int n = 0; |
|
|
|
char device_name[8] = {0}; |
|
|
|
bool found_ok = false; |
|
|
|
while(!found_ok && n<32) { |
|
|
|
|
|
|
|
int err; |
|
|
|
memset(&device_name, 0, 8); |
|
|
|
if( !parser.m_device.empty() ) |
|
|
|
sprintf(device_name, "%s:%i", parser.m_device.c_str(), n); |
|
|
|
else |
|
|
|
sprintf(device_name, "hw:%i", n); |
|
|
|
snd_card = std::string("hw:") + std::to_string(n); |
|
|
|
printf("..%s\n", snd_card.c_str()); |
|
|
|
|
|
|
|
err = snd_pcm_open (&pcm_handle, device_name, SND_PCM_STREAM_PLAYBACK, 0); |
|
|
|
err = snd_pcm_open (&pcm_handle, snd_card.c_str(), SND_PCM_STREAM_PLAYBACK, 0); |
|
|
|
if (err < 0) { |
|
|
|
if(errno == 16) { |
|
|
|
std::cout << "Device is occupied\n"; |
|
|
@ -416,18 +391,20 @@ int main(int argc, char *argv[]) |
|
|
|
found_ok = true; |
|
|
|
} |
|
|
|
|
|
|
|
if(!found_ok && argc<2) { |
|
|
|
if(!found_ok) { |
|
|
|
|
|
|
|
std::cout << "Sorry, cannot find sound device\n" << std::endl; |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
snd_card = std::string(device_name); |
|
|
|
if(!occupied_ok) |
|
|
|
snd_pcm_close(pcm_handle); |
|
|
|
} else if(!occupied_ok) { |
|
|
|
|
|
|
|
snd_pcm_close(pcm_handle); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
std::signal(SIGTERM, signal_handler); |
|
|
|
std::signal(SIGINT, signal_handler); |
|
|
|
std::signal(SIGQUIT, signal_handler); |
|
|
|
|
|
|
|
clist = makelist(); |
|
|
|
|
|
|
@ -488,7 +465,7 @@ int main(int argc, char *argv[]) |
|
|
|
f_ui = new functions_Ui(); |
|
|
|
|
|
|
|
Gtk::Main kit(argc, argv, true); |
|
|
|
AMixer::AMixer_Ui mixer(snd_card, scontents, arg0, progname, parser.m_systray, parser.x_pos, parser.y_pos, parser.width, parser.height, parser.m_hidden); |
|
|
|
AMixer::AMixer_Ui mixer(snd_card, scontents, arg0, progname, m_systray, x_pos, y_pos, width, height, m_hidden); |
|
|
|
kit.run(mixer); |
|
|
|
|
|
|
|
return EXIT_SUCCESS; |
|
|
|