SFML community forums

Bindings - other languages => D => Topic started by: malkierian on December 20, 2013, 03:50:23 am

Title: String, Dstring, and Char[] oh my...
Post by: malkierian on December 20, 2013, 03:50:23 am
OK, so I'm trying to use SFML's Audio module to play a sound, and I'm using the Windows headers to open the file (default Windows file dialog).  SoundBuffer.loadFromFile takes a "string" argument.  The Windows file dialog process takes a char[] array, and I am trying to use the return I get from the file select window to also form the default "tag", or in-program identifier, as a label as part of a sound actor class (custom class that handles play, stop and open buttons for a group, as well as the label), which also means I need to use a substring of the file name returned from the file select.  So essentially I need to go from char[] to string, and char[] to sub-dstring.  But I keep getting this error after picking the file and trying to load it:

std.utf.UTFException@E:\Dlang\dmd2\windows\bin\..\..\src\phobos\std\utf.d(1113): Invalid UTF-8 sequence (at index 1)

I am running the file selector in a separate function.  I have tried passing a pointer argument to the function to return through, and I've tried returning it directly, both fail.  How do I properly return a string/dstring argument from a function, and how do I properly/effectively convert between those three formats?
Title: Re: String, Dstring, and Char[] oh my...
Post by: Jebbs on December 20, 2013, 04:59:25 am
The string type is really just an alias for an array of immutable characters(immutable(char)[]). A really easy way to go from a char[] to a string is to make a copy of the array but with immutable data using idup.
char[] str1 = "String Literal!".dup;//make a mutable copy of the string literal
string str2 = str1.idup; //make a copy of the array with immutable data  

If you ever need to go to a char[] from a string, you can use std.conv's to function.
import std.conv;
string str1 = "String Literal!";
char[] str2 = to!(char[])(str1);

Is there any reason you need your substring to be a dstring? Why not also make it a string as well and just use a slice?

Title: Re: String, Dstring, and Char[] oh my...
Post by: malkierian on December 20, 2013, 05:42:49 am
Is there any reason you need your substring to be a dstring? Why not also make it a string as well and just use a slice?
I guess I may not have been clear enough in my original post, but SoundBuffer.loadFromFile() uses string, while Label.setString uses dstring, and neither will accept the other format.

EDIT: The biggest issue is that the Label.setString is the one I need to slice into, and that's what needs the dstring.  And when I try to do it (ala
Code: [Select]
label.setString(to!dstring(temp[(temp.lastIndexOf('\\') + 1)..(temp.length)].dup)); I get this error:
Code: [Select]
std.utf.UTFException@E:\Dlang\dmd2\windows\bin\..\..\src\phobos\std\utf.d(1113): Invalid UTF-8 sequence (at index 1), and I've already tested that setString works with a literal, and that slice actually works, believe it or not.  But when converting that slice to a dstring, if fails with that error I already mentioned.
Title: Re: String, Dstring, and Char[] oh my...
Post by: Jebbs on December 20, 2013, 06:12:59 am
It'll be hard to get this exactly right with out seeing any code, but you should be able to get the idea from the following pseudocode.
import std.conv;
char[] fileToLoad = getFileNameFromFilePicker();
audioBuffer.loadFromFile(fileToLoad.idup);
audioLabel.setString(to!(dstring)(fileToLoad[start..end]));

Hope that works for ya!
Title: Re: String, Dstring, and Char[] oh my...
Post by: malkierian on December 20, 2013, 06:33:00 am
Yeah, I think I edited my post after you replied.  I've tried that and it doesn't work.  It doesn't seem to work with anything but a literal.

EDIT:  After some creative Google searching, it seems that this is more a Dlang issue than it is an SFML issue.  Could there be something wrong in your binding that's causing it?
Title: Re: String, Dstring, and Char[] oh my...
Post by: Jebbs on December 20, 2013, 07:22:23 am
label is a Text instance, yes? I can't seem to reproduce the problem. Can you make a minimal example that reproduces the same issue?
Title: Re: String, Dstring, and Char[] oh my...
Post by: Jebbs on December 20, 2013, 07:59:46 am
EDIT:  After some creative Google searching, it seems that this is more a Dlang issue than it is an SFML issue.  Could there be something wrong in your binding that's causing it?

That could very well be the case, and is probably the most likely thing :P. If I can track it down I would be happy to get it fixed, but if I had a minimal example then it would be much easier.
Title: Re: String, Dstring, and Char[] oh my...
Post by: malkierian on December 21, 2013, 01:57:21 am
Oh my gosh, I think I figured it out.  So the file open dialog stuff is as follows:

auto openSoundFile()
{
        char[256] filenameBuffer;
        filenameBuffer[0] = 0;
        OPENFILENAME info;
        info.lStructSize = OPENFILENAME.sizeof;
        info.lpstrFilter = "Audio Files\0*.wav;*.ogg\0\0".ptr;
        info.lpstrFile = filenameBuffer.ptr;
        info.nMaxFile = filenameBuffer.length;
        if(GetOpenFileNameA(&info))
        {
                return to!string(filenameBuffer);
        }
        else return to!string("!!failed");
}

Apparently returning that as a string returns the entire char array, including the garbage after the file path, which my slice (temp.length - 1) then pulled for some reason.  Here's the code I'm using so you can at least try to debug if it's an issue in DSFML:

http://pastebin.com/Xfr53gNu

By the way, although the Text.setString works now, the program always stops responding when I uncomment the part for loading the SoundBuffer and I'm not sure why.
Title: Re: String, Dstring, and Char[] oh my...
Post by: Jebbs on December 21, 2013, 02:14:38 am
Cool. I should be able to get to this either tonight or tomorrow. I'll let you know when I have something!
Title: Re: String, Dstring, and Char[] oh my...
Post by: malkierian on December 21, 2013, 03:41:35 am
Update:  If I feed the loadFromFile function a lstring literal, it still freezes the program.  This is a valid WAV file I'm trying to load, not even an Ogg.
Title: Re: String, Dstring, and Char[] oh my...
Post by: malkierian on December 23, 2013, 01:07:55 am
By way of bumping, I just wanted to report that Ogg files don't work with that code I posted either.  Same freezing.  Also, the message I get in console is

Stream closed?
Stream closed?

Yes, I get it twice for one file operation.
Title: Re: String, Dstring, and Char[] oh my...
Post by: malkierian on December 23, 2013, 06:27:52 am
And another development arrives.

So I tried adding a try...catch around my call to SoundBuffer.loadFromFile(), and while it is obviously erroring (I put an error message in there) since I caught the error, it actually goes on to load and play the sound fine.  I have no freaking idea what's going on at this point.

Here's the most basic code you could want to test it:
module main;

import dsfml.audio;
import dsfml.graphics;
import dsfml.window;

import std.stdio;

void main(string[] args)
{
//      new Soundboard().run();
        auto window = new RenderWindow(VideoMode(1280, 720), "Virtual Soundboard", Window.Style.Titlebar | Window.Style.Close);
        auto buffer = new SoundBuffer();
        auto sound = new Sound();
        writeln("Buffer and Sound instantiated");
        try
        {
                if(!buffer.loadFromFile("F:\\Soundboard\\Ogg\\AirLeak.ogg"))
                        return;
                writeln("Buffer loaded");
        }
        catch
        {
                writeln("Error loading file to buffer");
        }
        sound.setBuffer(buffer);
        sound.play();
        while (window.isOpen())
        {
                Event event;
                while(window.pollEvent(event))
                {
                        if(event.type == Event.EventType.Closed)
                        {
                                window.close();
                        }
                }
               
                window.clear(Color.Black);
               
                window.display();
        }
}
Just put in whatever sound file you want for the buffer and try commenting the try...catch.  It'll freeze.  But with it in there, it tells you in the console that there was an error loading the buffer (which I believe, if you run it without the try catch, it will tell you is an access violation in that line), but then successfully plays it before starting the main loop.

EDIT: This hack only seems to work for OGG files.  Try to do that with a WAV and it will still freeze the program.  And when the OGG file continues, it actually gives a core.exception.InvalidMemoryOperationError instead of an access violation.  This is extremely weird...

EDIT 2:  Even with that hack, it doesn't work every time, and I can't track down why not.

EDIT 3:  ACK!  It appears that every fifth time I run the program it works, and every now and then it will even load WAVs on that successful run.  WHAT THE HECK IS GOING ON?!  LOL.  This is so perplexing.
Title: Re: String, Dstring, and Char[] oh my...
Post by: Jebbs on December 23, 2013, 10:08:16 pm
I just started vacation from work today, so you can expect me to dig into this very soon!

Also, the message I get in console is

Stream closed?
Stream closed?

Yes, I get it twice for one file operation.

Yikes! Looks like I had testing code still present in the libs I sent you before. I doubt this will fix your problem, but at the very least use the new ones I recently posted links to in the nightly thread.
Title: Re: String, Dstring, and Char[] oh my...
Post by: Jebbs on December 24, 2013, 09:27:54 am
So, using the nightly DSFML-C build and modifying parts of your code, it worked fine for me(save for a new error I found in the Sound class that I now need to track down).

Your original code for choosing the file was this:

auto openSoundFile()
{
        char[256] filenameBuffer;
        filenameBuffer[0] = 0;
        OPENFILENAME info;
        info.lStructSize = OPENFILENAME.sizeof;
        info.lpstrFilter = "Audio Files\0*.wav;*.ogg\0\0".ptr;
        info.lpstrFile = filenameBuffer.ptr;
        info.nMaxFile = filenameBuffer.length;
        if(GetOpenFileNameA(&info))
        {
                return to!string(filenameBuffer);
        }
        else return to!string("!!failed");
}

However, the original code that Adam Ruppe posted in the D forums didn't return the entire char array. It returned a pointer to it. Correcting that fixes all your problems because a C char* uses \0 as a finalizer, so the to!string function works like it is supposed to. Using to!string on the whole of fileNameBuffer will convert the entire thing, giving you the garbage characters at the end of the good stuff.

Anyways, here's the same code with the revisions I made. http://pastebin.com/nR4WJVx8

A couple of notes about your code:

Color is a struct, so you can skip using "new" when you create Color objects. That way, you don't have to dereference it when you call Window.clear.

When getting a slice, you can actually use "$" as a shorthand for the length of the array.

Hope all that helps!
Title: Re: String, Dstring, and Char[] oh my...
Post by: malkierian on December 24, 2013, 05:09:32 pm
Thanks for the tips, you're right that works perfectly on its own.  But if I try to put it back into my real code for the program, I still get the freezing.  And I still get those debug messages, so apparently I've still got your debug code in there somehow despite rebuilding DSFML and using the latest DSFML-C nightlies.  Perhaps I'm doing that wrong.  When we get that other thread sorted out, I'll try this again.
Title: Re: String, Dstring, and Char[] oh my...
Post by: malkierian on December 28, 2013, 01:32:50 am
Alright, I figured out that the issue with the debug stuff was that I had forgotten to copy the .dll files into my project workspace so it would copy the new ones instead of the old ones.  However, despite not getting the "Stream closed?" message, it still freezes on me when trying to load the file from the path given by the file window.  If it's OK with you, I'd like to send you a zip with my project inside so you can look at this yourself, because I must obviously be missing something (and it consists of 5 source files, some images, etc).
Title: Re: String, Dstring, and Char[] oh my...
Post by: Jebbs on December 28, 2013, 01:42:33 am
Sure. I'd be glad to look at it.

My email is dehaan.jeremiah@gmail.com
Title: Re: String, Dstring, and Char[] oh my...
Post by: malkierian on December 29, 2013, 07:17:47 am
Any luck with this, Jebbs?
Title: Re: String, Dstring, and Char[] oh my...
Post by: Jebbs on December 29, 2013, 07:30:40 am
Haven't been able to get to it quite yet, sorry. Work is slowing down for the now though, so I'll get off pretty early tomorrow.  I planned on looking at this then and I'll let you know once I see something!
Title: Re: String, Dstring, and Char[] oh my...
Post by: malkierian on December 29, 2013, 08:45:16 am
Ah, ok, no problem.
Title: Re: String, Dstring, and Char[] oh my...
Post by: Jebbs on December 29, 2013, 10:36:57 pm
Had a chance to look at some code!

It took me a bit to get things set up since I didn't have any Derelict stuff, so I just added the source files directly instead of messing around with building static libraries. The ones I used were https://github.com/DerelictOrg/DerelictAL and https://github.com/DerelictOrg/DerelictUtil, which could be newer than what you are using since all of the OpenAL stuff is in a single file now as opposed to being in derelict.openal.al, derelict.openal.types, and derelict.openal.functions.

Any who, the only changes I made to your files were in soundactor.d, where I commented out importing derelict.openal.types and derelict.openal.functions, and then I uncommented lines 105:
sound.setBuffer(buffer);
and 107:
label.setString(to!(dstring)(temp[(temp.lastIndexOf('\\') + 1)..$ - 4].dup));

Once I added libsndfile-1.dll into the bin folder, I ran it, selected a file, and then hit the play button....and well, it worked. Granted, I did get some runtime memory errors on occasion which are probably related to the sound class(I know how I'll fix them), but it loaded the sound file(I used both a .wav and a .ogg) and played it. It would only play a single file each time I ran the program, though. It worked in both debug and release configurations. I used my own dsfml-xxx-2.lib files, but I used the included dll's.



So...yeah.. I really wish I could help but I don't know what I could do. Unless there was more that I needed to uncomment to see the error, it sounds like it is something in your own code.
Title: Re: String, Dstring, and Char[] oh my...
Post by: malkierian on December 29, 2013, 10:53:07 pm
Could you send me your DSFML lib and dll files so I could test it to make sure it wasn't because I was building it wrong?  I'll try updating my build of Derelict as well.

On a separate note, I'm starting to think that I must be missing more drivers, or it's trying to load more 64-bit drivers, as if I don't have libsndfile-1.dll copying over to the directory, it doesn't run at all.