Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » Developing U++ » U++ Developers corner » Sound in linux (Lack of standards in Linux is a problem but there are some near-standards)
Sound in linux [message #44031] Tue, 16 December 2014 10:51 Go to next message
rainbowsally is currently offline  rainbowsally
Messages: 29
Registered: December 2014
Promising Member
These are freedesktop sounds but I don't know what installed them. They were in my suse 11.4 and my mint 15

/usr/share/sounds/freedesktop/stereo/dialog-error.oga
/usr/share/sounds/freedesktop/stereo/dialog-warning.oga
/usr/share/sounds/freedesktop/stereo/dialog-information.oga

Probably the most generic player with ability to suppress commandline noise is sox. It installs the
/usr/bin/play program.

Here's what I have for uppsrc/Core/Util.cpp for the linux sounds.

---------
#ifdef PLATFORM_POSIX
static void LinuxBeep(const char *fn)
{
//	return;
//	// This is not the right way to do that... (causes zombies, 
// ignores Gnome settings)
	char hb[100];
	char* h = hb; // so we can see the string in the debugger
	sprintf(h, "play -q /usr/share/sounds/freedesktop/stereo/dialog-%s.oga 2>/dev/null &", fn);
//	strcat(h, fn);
//#ifdef CPU_BLACKFIN
//	if(vfork()) return;
//#else
//	if(fork()) return;
//#endif
//	IGNORE_RESULT(
		0 == system(h);
//	);
//	_exit(EXIT_SUCCESS);
}
#endif

void BeepInformation()
{
#ifdef PLATFORM_WIN32
	MessageBeep(MB_ICONINFORMATION);
#else
	LinuxBeep("information");
#endif
}

void BeepExclamation()
{
#ifdef PLATFORM_WIN32
	MessageBeep(MB_ICONEXCLAMATION);
#else
	LinuxBeep("warning");
#endif
}

void BeepQuestion()
{
#ifdef PLATFORM_WIN32
	MessageBeep(MB_ICONQUESTION);
#else
	LinuxBeep("information");
//	write(1, "\a", 1); //??
#endif
}

---------------

UPP is so cool it hurts. Smile Thank you.

Re: Sound in linux [message #44038 is a reply to message #44031] Wed, 17 December 2014 11:30 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
rainbowsally wrote on Tue, 16 December 2014 10:51
These are freedesktop sounds but I don't know what installed them. They were in my suse 11.4 and my mint 15

/usr/share/sounds/freedesktop/stereo/dialog-error.oga
/usr/share/sounds/freedesktop/stereo/dialog-warning.oga
/usr/share/sounds/freedesktop/stereo/dialog-information.oga

Probably the most generic player with ability to suppress commandline noise is sox. It installs the
/usr/bin/play program.



Thanks, I have taken your code and started investigating; ended with something like this:

#ifdef PLATFORM_POSIX

String CurrentSoundTheme = "freedesktop";

static void LinuxBeep(const char *name)
{
	String fn = "/usr/share/sounds/" + CurrentSoundTheme + "/stereo/dialog-" + name;
	system("play -q  " + fn + (FileExists(fn + ".ogg") ? ".ogg" :
                               FileExists(fn + ".oga") ? ".oga" :
                               FileExists(fn + ".wav") ? ".wav" :
                               ".*")
	       + " >/dev/null 2>/dev/null&");
}

#endif

void BeepInformation()
{
#ifdef PLATFORM_WIN32
	MessageBeep(MB_ICONINFORMATION);
#else
	LinuxBeep("information");
#endif
}

void BeepExclamation()
{
#ifdef PLATFORM_WIN32
	MessageBeep(MB_ICONEXCLAMATION);
#else
	LinuxBeep("warning");
#endif
}

void BeepError()
{
#ifdef PLATFORM_WIN32
	MessageBeep(MB_ICONERROR);
#else
	LinuxBeep("error");
#endif
}

void BeepQuestion()
{
#ifdef PLATFORM_WIN32
	MessageBeep(MB_ICONQUESTION);
#else
	LinuxBeep("question");
#endif
}



then in ChGtk:

	CurrentSoundTheme = GtkStyleString("gtk-sound-theme-name");


seems to work fine, playing sounds from selected theme. So from now on, thanks to you, U++ finally started to beep in Linux Smile

Mirek
Re: Sound in linux [message #44042 is a reply to message #44038] Wed, 17 December 2014 18:54 Go to previous messageGo to next message
rainbowsally is currently offline  rainbowsally
Messages: 29
Registered: December 2014
Promising Member
The changes in Core/Util.cpp work, but I got errors when I dropped the other snippet into ChGtk.cpp. It looks like a snippet from inside a function?

So I commented it out for now.

Works. Smile

Finding the right place to plug it in may be a little confusing for others so in case anyone else wants to play with this, I'll upload the uppsrc/Core/Util.cpp per your changes here.

  • Attachment: Util.cpp
    (Size: 15.68KB, Downloaded 315 times)
Re: Sound in linux [message #44044 is a reply to message #44042] Wed, 17 December 2014 19:56 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
rainbowsally wrote on Wed, 17 December 2014 18:54
The changes in Core/Util.cpp work, but I got errors when I dropped the other snippet into ChGtk.cpp. It looks like a snippet from inside a function?

So I commented it out for now.

Works. Smile

Finding the right place to plug it in may be a little confusing for others so in case anyone else wants to play with this, I'll upload the uppsrc/Core/Util.cpp per your changes here.



No worry, it is already in trunk and next nightly build... Smile
Re: Sound in linux (& generic launchers) [message #44045 is a reply to message #44038] Thu, 18 December 2014 04:23 Go to previous messageGo to next message
rainbowsally is currently offline  rainbowsally
Messages: 29
Registered: December 2014
Promising Member
Yuh know?

The lack of standards in Linux is really a problem.

Here's the problem, linux guys.
ls /usr/share/sounds/freedesktop/stereo/*-warning.*
ls /usr/share/sounds/freedesktop/stereo/*-information.*
ls /usr/share/sounds/freedesktop/stereo/*-question.*


See it? The question sound (a symlink to one of the basic sounds) is inconsistent with the other two dialog sounds and is probably misnamed.

This is the sound string I'd recommend for "question" that should have the greatest probability of being portable.
void BeepQuestion()
{
#ifdef PLATFORM_WIN32
	MessageBeep(MB_ICONQUESTION);
#else
	LinuxBeep("warning");
#endif
}


There may be a ton of interesting sounds for KDE and possibly GTK in the directory above these, but as far as standards go, freedesktop.org is the closest we've got to a standard at this point.

/////////// And Generic Launchers /////////

[There's a question at the bottom.]

There are MANY more problems with linux GUI toolkits, though. And I'm not sure that this is the place to bring them up, but in GUIs we expect things to run concurrently. We don't expect things like playing sounds to block (that is, to wait until the sound is finished) before painting a window. And we don't want to have to create a new library of new non-standard sounds that blow our applications up in size due to the impracticality of compressing these things.

There are ways to accomplish this by way of shell calls, but (again) there is no basic binutils or coreutils level of linux utility to do this.

Examples of applications that do shell calls that run concurrently, by way of reparenting the called process to 'init' are kshell3, 4, or 5. I have kshell4. It genuinely returns before the sound is finished playing.

In kde compare [Note the lowercase Q switch. Don't use P].
play -q /usr/share/sounds/KDE-Sys-Log-In-Long.ogg
to
kshell4 play -q /usr/share/sounds/KDE-Sys-Log-In-Long.ogg
and if you try the launch utility, try that as well.
launch play -q /usr/share/sounds/KDE-Sys-Log-In-Long.ogg


And for superuser, there kdesu, kdesudo, gksu, and xdg-su, and others which also reparent the called application to init. But they are meant for running GUIs from the commandline as superuser. That's overkill and in fact not at all what we want.

Here's a simple app, that returns immediatly, generically, leaving a very small footprint in memory while the called shell runs.

I confess, I haven't run valgrind on it and that might not be the only problem with it, though I have used it for years and will continue to use it unless or until something better turns up.

I called it "launch". And you probably won't like it. But I love it. Smile

Here's the main function.

int main(int argc, char** argv)
{
  int err = 0;
  
  // help and version switches
  if(argc == 1)
    return usage(0);
  
  if(argc == 2)
  {
    if(strcmp(argv[1], "--help") == 0)
      return usage(0);
    if(strcmp(argv[1], "-v") == 0)
      return print_version(0);
  }

  err = parse_options(argc, argv);
  if(err) 
  {
    printf("Unknown launch option '%s'\n", argv[err]);
  }
  
  // reassemble commandline
  char args[1024];
  err = unparse_args(args, 1000, argc, argv);
  if(err)
  {
    if(err == ENOMEM)
      fprintf(stderr, "Out of memory or args list too long\n");
    else if (err == E2BIG)
      fprintf(stderr, "Argument list too long\n");
    return 1;
  }

  // if -q suppress all feedback from the app
  if(!flg.warn)
  {
    fclose(stdout);
    fclose(stderr);
    strcat(args, " > /dev/null 2>&1");
  }

  // do the fork and execute the commandline
  pid_t pid;

  pid = fork ();
  if (pid == 0)
  {
    

    // command path, command name, arg1, arg2, ...
    execl ("/bin/sh", "sh", "-c", args, NULL);

    // _exit(code) for threads and forks.
    _exit (EXIT_FAILURE);
  }
  else if (pid < 0)
    return -1;
  else
    return 0;
}



And I'll attach the missing pieces as a tarball in case anyone is curious about this thing or has any ideas as to how to improve it.

The binary and sources, and makefile are all included. I believe the executable is the debug version.

If you watch the processes with gnome-system-monitor or ksysguard (or ps -ax or ???) you will see that the application runs under init and the footprint is very reasonable. The switches allow feedback but the default is to run silently.

Question: Is it possible to launch an invisible window to run these "shells" in UPP so that we get concurrently running applications without having to use external tools such as kshell<N> or 'launch" while retaining the ability to shut them down and possibly kill applications that hang if they exceed a reasonable timeout?

Re: Sound in linux (& generic launchers) [message #44046 is a reply to message #44045] Thu, 18 December 2014 06:35 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

rainbowsally wrote on Thu, 18 December 2014 04:23
Question: Is it possible to launch an invisible window to run these "shells" in UPP so that we get concurrently running applications without having to use external tools such as kshell<N> or 'launch" while retaining the ability to shut them down and possibly kill applications that hang if they exceed a reasonable timeout?

Hi,

There is no need for an invisible window. Just remember the pid returned from fork and call kill on it after the timeout is exceeded. In GUI apps, you can do this easily using SetTimeCallback().

Best regards,
Honza
Re: Sound in linux [message #44053 is a reply to message #44031] Fri, 19 December 2014 14:45 Go to previous messageGo to next message
rainbowsally is currently offline  rainbowsally
Messages: 29
Registered: December 2014
Promising Member
Hi Honza.

Quote:

There is no need for an invisible window. Just remember the pid returned from fork and call kill on it after the timeout is exceeded. In GUI apps, you can do this easily using SetTimeCallback().


Technically, you're right, but getting GUIs and the old terminal based linuxes is not so straight forward.

For example how could you get the PID without "waitpid()" or reading a return string from a system() call.

The calling app would hang so you'd never get a chance to shut it down.

A system call to an intermediate shell utility similar to kshell<N> is a much better alternative for a simple dialog bell of some sort.

Either it runs or it doesn't.

But I see now that the "invisible window" thing wouldn't work either. Not sure how this "shell" utility could be integrated into UPP. Maybe run the fork in another thread. Then I suppose that thread's binary image would be all that gets copied to memory.

It's going to take me a while to get up to speed here.

Thanks for UPP and this forum. Smile

-rs
Re: Sound in linux [message #44065 is a reply to message #44053] Sun, 21 December 2014 21:04 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

rainbowsally wrote on Fri, 19 December 2014 14:45
Hi Honza.

Quote:

There is no need for an invisible window. Just remember the pid returned from fork and call kill on it after the timeout is exceeded. In GUI apps, you can do this easily using SetTimeCallback().


Technically, you're right, but getting GUIs and the old terminal based linuxes is not so straight forward.

In U++ there is even ready to use solution for non-GUI apps. See bazaar/Timer. Or you could write your own, based on thread, or POSIX alarms, or any from many other suitable technologies.

rainbowsally wrote on Fri, 19 December 2014 14:45
For example how could you get the PID without "waitpid()" or reading a return string from a system() call.

The calling app would hang so you'd never get a chance to shut it down.

The fork() call in your previous example returns the pid of child process to the parent. There is no need to block on the waitpid, it should only be called to collect the finished processes. If you don't want it to block your application, you can use it with the NOHANG option.

rainbowsally wrote on Fri, 19 December 2014 14:45
A system call to an intermediate shell utility similar to kshell<N> is a much better alternative for a simple dialog bell of some sort.

Either it runs or it doesn't.

Calling shell just to run a command is in most cases unnecessary overkill. The shell actually does pretty much the same thing as described above.

Honza
Re: Sound in linux [message #44067 is a reply to message #44065] Mon, 22 December 2014 08:01 Go to previous messageGo to next message
rainbowsally is currently offline  rainbowsally
Messages: 29
Registered: December 2014
Promising Member
Quote:


Calling shell just to run a command is in most cases unnecessary overkill. The shell actually does pretty much the same thing as described above.

Honza


Possibly.

But let's say you launch a shell with a command to.. let's say 'find' everything on your C drive and dump it into a text file.

Anything, just something that takes a long time would do.

If this shell is launched by way of a stystem() call from a GUI, will the GUI hang until 'find' is done?

Seems to me it does. Maybe not with the '&' at the end though.

In QT the buttons didn't pop back up until the system call was finished.

[I'm not being lazy and not checking this out, I'm just too busy at the moment.]

Re: Sound in linux [message #44071 is a reply to message #44067] Mon, 22 December 2014 09:56 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1789
Registered: August 2008
Location: Czech Republic
Ultimate Contributor

rainbowsally wrote on Mon, 22 December 2014 08:01
But let's say you launch a shell with a command to.. let's say 'find' everything on your C drive and dump it into a text file.

Anything, just something that takes a long time would do.

If this shell is launched by way of a stystem() call from a GUI, will the GUI hang until 'find' is done?

From the man page of system():
Quote:

The system() library function uses fork(2) to create a child process
that executes the shell command specified in command using execl(3) as
follows:

execl("/bin/sh", "sh", "-c", command, (char *) 0);

system() returns after the command has been completed.

So to answer your question, yes it blocks. But you can always call fork() and one of the exec* functions (there is about six of them). That in itself is not blocking, later you can check if the process is completed by calling waitpid(pid_returned_from_fork, &return_code, NOHANG), which is also nonblocking operation.

Honza
Re: Sound in linux [message #44079 is a reply to message #44071] Tue, 23 December 2014 09:40 Go to previous messageGo to next message
rainbowsally is currently offline  rainbowsally
Messages: 29
Registered: December 2014
Promising Member
Hi Honza.

Quote:
From the man page of system():
----------
The system() library function uses fork(2) to create a child process
that executes the shell command specified in command using execl(3) as
follows:

execl("/bin/sh", "sh", "-c", command, (char *) 0);

system() returns after the command has been completed.
----------

So to answer your question, yes it blocks. But you can always call fork() and one of the exec* functions (there is about six of them). That in itself is not blocking, later you can check if the process is completed by calling waitpid(pid_returned_from_fork, &return_code, NOHANG), which is also nonblocking operation.

Honza


True. Smile

Now here's a trickier one. How might we launch an app in another thread, that we KNOW will take a long time, and shut it down with calls to STOP and CONTINUE from time to time, in order to assure that the GUI continues to be responsive during a system() call.

Re: Sound in linux [message #44083 is a reply to message #44079] Tue, 23 December 2014 13:32 Go to previous messageGo to next message
rainbowsally is currently offline  rainbowsally
Messages: 29
Registered: December 2014
Promising Member
Honza, one more thing.

Threads are disabled in Linux by default. I think I know why, and I think there's an easy fix (re. the intermittent crash problem and thread timing), but at this point, we can't count on running in a separate thread working for all non-windows users.

I have enabled threads for myself though and eventually will get around to experimenting with them.

I'll check out the UPP AltThreads package in a few minutes.
Re: Sound in linux [message #44084 is a reply to message #44083] Tue, 23 December 2014 14:49 Go to previous messageGo to next message
Klugier is currently offline  Klugier
Messages: 1075
Registered: September 2012
Location: Poland, Kraków
Senior Contributor
Hello,

I think there is a problem with this code. "play" command is not install by default on my distribution (Kubuntu), so the sound cannot be played. Alternatively, I can use command "ogg123" to play .ogg audio file.

So, I am almost sure that above solution is not distribution independent and should be improved for example if "play" is not detected use "ogg123" instead.

Sincerely,
Klugier


U++ - one framework to rule them all.
Re: Sound in linux [message #44087 is a reply to message #44084] Wed, 24 December 2014 04:40 Go to previous messageGo to next message
rainbowsally is currently offline  rainbowsally
Messages: 29
Registered: December 2014
Promising Member
Hi Klugier.

On my system, I don't have ogg123 (at this time). I have gst123 (a gstreamer version with a bit more flexibility).

There's so many variations in linux. And xdg-open won't play anything if there's no mime-link set for it.

Your solution works, but it's probably even less generic than 'play'.

"play" is in the sox package and handles all kinds of different sound formats, not just ogg/vorbis stuff. It's a commandline utility but it is very handy to convert between audio formats.

But if you've got what you need now, you probably don't need to get sox. It's a bit overkill, though it is quite useful at times.


Klugier wrote on Tue, 23 December 2014 14:49
Hello,

I think there is a problem with this code. "play" command is not install by default on my distribution (Kubuntu), so the sound cannot be played. Alternatively, I can use command "ogg123" to play .ogg audio file.

So, I am almost sure that above solution is not distribution independent and should be improved for example if "play" is not detected use "ogg123" instead.

Sincerely,
Klugier

Re: Sound in linux [message #44094 is a reply to message #44084] Wed, 24 December 2014 12:27 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Klugier wrote on Tue, 23 December 2014 14:49
Hello,

I think there is a problem with this code. "play" command is not install by default on my distribution (Kubuntu), so the sound cannot be played. Alternatively, I can use command "ogg123" to play .ogg audio file.

So, I am almost sure that above solution is not distribution independent and should be improved for example if "play" is not detected use "ogg123" instead.

Sincerely,
Klugier


You are welcome to propose the patch. Anyway, at the moment, using 'play' means going from being silent on all distros to being silent on just some. I guess that is an improvement Smile

Mirek
Re: Sound in linux [message #44096 is a reply to message #44094] Wed, 24 December 2014 13:18 Go to previous messageGo to next message
Klugier is currently offline  Klugier
Messages: 1075
Registered: September 2012
Location: Poland, Kraków
Senior Contributor
Hello Mirek,

The detection can be done in following way:
// Copy from PrinterJob.cpp -> I think it should be part of POSIX U++ library!!!
static String System(const char *cmd, const String& in)
{
	String ofn = GetTempFileName();
	String ifn = GetTempFileName();
	SaveFile(ifn, in);
	String c = cmd;
	c << " >" << ofn;
	if(in.GetCount())
		c << " <" << ifn;
	String q;
	if(system(c) >= 0)
		q = LoadFile(ofn);
	FileDelete(ofn);
	FileDelete(ifn);
	return q;
}

static String FindPlayer()
{
	static String player;
	
	if (player.IsEmpty()) {
		const char *players[] = { "play", "ogg123" }; // <- Add all possible players here!!!
		
		for (int i = 0; i < __countof(players); i++) {
			if (!System("which " + String(players[i]), Null).IsEmpty()) {
				player = players[i];
				break;
			}
		}
	}
	
	return player;
}

static void LinuxBeep(const char *name)
{
	String player = FindPlayer();
	if (!player.IsEmpty()) {
		String fn = "/usr/share/sounds/" + CurrentSoundTheme + "/stereo/dialog-" + name;
		system(player + " -q " + fn + (FileExists(fn + ".ogg") ? ".ogg" :
        	                           FileExists(fn + ".oga") ? ".oga" :
        	                           FileExists(fn + ".wav") ? ".wav" :
        	                           ".*")
	    	   + " >/dev/null 2>/dev/null&");
	}
}


IMO, There is a problem that function "System" is not part of U++ (I don't want to do copy&past). Can we do something with that issue?

Sincerely,
Klugier
  • Attachment: Sound.diff
    (Size: 1.79KB, Downloaded 225 times)


U++ - one framework to rule them all.

[Updated on: Wed, 24 December 2014 13:21]

Report message to a moderator

Re: Sound in linux [message #44098 is a reply to message #44096] Wed, 24 December 2014 15:46 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Maybe use Sys instead?
Re: Sound in linux [message #44100 is a reply to message #44098] Wed, 24 December 2014 16:30 Go to previous messageGo to next message
Klugier is currently offline  Klugier
Messages: 1075
Registered: September 2012
Location: Poland, Kraków
Senior Contributor
Hello Mirek,

It seems that "Sys" works perfect...

static String FindPlayer()
{
	static String player;
	if (player.IsEmpty()) {
		const char *players[] = { "play", "ogg123", "gst123" };
		for (int i = 0; i < __countof(players); i++) {
			String out;
			if (Sys("which " + String(players[i]), out) == 0 && !out.IsEmpty()) {
				player = players[i];
				break;
			}
		}
	}
	return player;
}

static void LinuxBeep(const char *name)
{
	String player = FindPlayer();
	if (!player.IsEmpty()) {
		String fn = "/usr/share/sounds/" + CurrentSoundTheme + "/stereo/dialog-" + name;
		system(player + " -q " + fn + (FileExists(fn + ".ogg") ? ".ogg" :
        	                           FileExists(fn + ".oga") ? ".oga" :
        	                           FileExists(fn + ".wav") ? ".wav" :
        	                           ".*")
	    	   + " >/dev/null 2>/dev/null&");
	}
}


I enclose also diff...

----------------------------
But, all this applications needs user installation. So, sound out of the box (without installation any package) seems to be hard. We can also make additional dependency for example with "sox" package (Debian base distribution).
----------------------------
Next problem is GCC warning, because we ignore system return value. What should we do?

int status = system(...)
if (status == -1) return; // <- Throw exception???


Sincerely,
Klugier
  • Attachment: Sound.diff
    (Size: 1.41KB, Downloaded 240 times)


U++ - one framework to rule them all.

[Updated on: Wed, 24 December 2014 20:03]

Report message to a moderator

Re: Sound in linux [message #44103 is a reply to message #44100] Thu, 25 December 2014 10:48 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Thanks, modified version of this code applied to trunk...

Mirek
Re: Sound in linux [message #44105 is a reply to message #44103] Thu, 25 December 2014 13:56 Go to previous messageGo to previous message
Klugier is currently offline  Klugier
Messages: 1075
Registered: September 2012
Location: Poland, Kraków
Senior Contributor
Hello Mirek,

I think you should also protect the situation when player string is empty. It can leads to meaningless system call, that cost more resources than normal function call. The system needs to detect that invoking command is wrong.

Code:
if (!player.IsEmpty()) {
		String fn = "/usr/share/sounds/" + CurrentSoundTheme + "/stereo/dialog-" + name;
		// Call only if player is detected!!!
                IGNORE_RESULT(system(player + " -q " + fn +
	    	          (FileExists(fn + ".ogg") ? ".ogg" :
	        	       FileExists(fn + ".oga") ? ".oga" :
                	   FileExists(fn + ".wav") ? ".wav" :
                      ".*")
	              + " >/dev/null 2>/dev/null&"));
}


Sincerely,
Klugier


U++ - one framework to rule them all.

[Updated on: Thu, 25 December 2014 13:57]

Report message to a moderator

Previous Topic: Raster::Line segfaults ... sometimes.
Next Topic: Adding network proxy support to U++
Goto Forum:
  


Current Time: Thu Mar 28 16:46:41 CET 2024

Total time taken to generate the page: 0.01203 seconds