Forum Xamarin.iOS

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

Problem with binding Objective-C protocols

tescotttescott USMember ✭✭

I'm trying to accomplish nearly the same thing as outlined in this StackOverflow question.

I've got a 3rd party library (ObjectAL), that contains a class that has a method with a return type of:

`

  • (id) playEffect:(NSString*) filePath;
    `

I define this method in the binding interface as:

[Export ("playEffect:")] ALSoundSource playEffect(string filePath);

Further, I try to define an ALSoundSource interface as follows:

[BaseType (typeof (NSObject))] [Model] interface ALSoundSource { [Export ("playing")] bool playing { get; } // ... more code... }

Doing this, I run into the same type of error experienced by the author of the SO question:

System.InvalidCastException: Unable to cast object of type 'MonoTouch.Foundation.NSObject' to type 'objectal.ALSoundSource'.

Does anyone have insight on the proper approach to get this binding to work?

Thanks,
--tim

Posts

  • tescotttescott USMember ✭✭

    Just a quick follow-up. I found this thread and used that as a guide:

        interface ALSoundSourceProtocol
        {
            [Export ("playing")]
            bool playing { get; }
        }
    
        [BaseType (typeof (NSObject))]
        interface OALSimpleAudio
        {
            // snip
    
            [Export ("playEffect:")]
            ALSoundSource playEffect(string filePath);
    
            // snip
        }
    
    
        [BaseType (typeof (NSObject))]
        interface ALSoundSource : ALSoundSourceProtocol 
        {
    
        }
    

    No difference in the end result. I still hit the System.InvalidCastException.

    --tim

  • tescotttescott USMember ✭✭
    edited December 2012

    FYI--

    I got this working by diving deep down the rabbit hole and changing the ALSoundSource references to ALSource, which is ultimately returned and implements the ALSoundSource protocol. This aligns with the suggestion provided in this StackOverflow thread.

    --tim

  • tescotttescott USMember ✭✭

    Monotouch bindings that work for the OALSimpleAudio portion of ObjectAL are here:

    https://github.com/tescott/objectal-monotouch

    Hope this helps someone else out there.

    --tim

  • I've just come across your library - looks great and just what I was hoping to find!

    Can I ask what the status of the ALSoundSource bit is now? I know the doc says only
    Simple audio is implemented (I need polyphonic sound) but the ALSoundSource bit looks
    pretty complete to my untrained eye. Is it working?

    Thanks,

    Clive

  • tescotttescott USMember ✭✭
    edited December 2012

    Clive,

    It's completely untested... so, I have no idea if it works or not. I was on a roll when I did the binding so I ended up adding all the properties and methods for ALSoundSource. I have not tried them myself -- I'm only using the OALSimpleAudio for my sound work. HOPEFULLY ALSoundSource works. How's that for re-assurance? :)

    I imagine you should be able to get a really simple test project going. If you find anything or would like to contribute some tests, please let me know.

    Thanks,
    --tim

  • Cheers - I'll give it a try when I can (probably a few days). I've got an app that works with Xamarin's OpenAL, reverb apart, so I should be able to use that as a test harness. Can't be worse than beating my head against the xamarin openal wrapper :-)

  • tescotttescott USMember ✭✭

    Clive,

    Were you ever able to come up with tests to check things out? I'm curious what you have found.

    --tim

  • Sorry for the delay; have plugged in your ObjectAL binding, and it works very well! One unfortunate problem though: the global setReverbOn switches (which hang off the listener apparently) are not exposed, so I'm struggling to switch reverb on. In particular, I think these functions are missing:

    // Turn on reverb.
    [OALSimpleAudio sharedInstance].context.listener.reverbOn = YES;
    
    // Set global reverb level to "normal" (0dB)
    [OALSimpleAudio sharedInstance].context.listener.globalReverbLevel = 0;
    
    
    [OALSimpleAudio sharedInstance].context.listener.reverbRoomType = [roomType intValue];
    

    I suspect if I had these in place, reverb would work nicely; any nice hints as to what to add to ApiDefinition.cs please? :-)

  • tescotttescott USMember ✭✭

    I'll see how difficult it is to expose these. I'll keep you posted.

    --tim

  • Thanks - you're a star!

  • tescotttescott USMember ✭✭

    I've created a .dll that hopefully includes what you need. No clue if it works. Before I commit things to the Github repo, can you test it out? Please let me know where to send it.

    --tim

  • tescotttescott USMember ✭✭

    Alright, I created a test for things and finally got it working. Give me another couple of days to flesh out the various bindings. I only exposed the bare essentials to see if I could get the reverb part going.

    For reference, here's what I did for verification in my test. Not quite as straight forward as I thought it would be since you have to use the ALBuffer to get things to work correctly as well as force the sound to Mono:

            objectal.OALSimpleAudio.sharedInstance ().reservedSources = 0;
            objectal.OALSimpleAudio.sharedInstance ().context.listener.reverbOn = true;
            objectal.OALSimpleAudio.sharedInstance ().context.listener.globalReverbLevel = 0;
            ALSource sourcex = (ALSource)ALSource.source ();
            sourcex.reverbSendLevel = 1.0f;
    
            objectal.OALSimpleAudio.sharedInstance ().context.listener.reverbRoomType = (int)roomType.ALC_ASA_REVERB_ROOM_TYPE_LargeHall2;
    
            objectal.OALSimpleAudio.sharedInstance ().allowIpod = false;
            objectal.OALSimpleAudio.sharedInstance ().honorSilentSwitch = true;
            ALBuffer buffer = objectal.OALSimpleAudio.sharedInstance ().preloadEffect ("data/TileGroup1.caf", true);
    
            sourcex.play (buffer,true);
    
            while (sourcex.playing) {
            }
    
  • That's great - looking forward to giving it a go! If you want to mail the lib to me, I'm at [email protected]

    Thanks again!

Sign In or Register to comment.