HydrogenAudio

Hosted Forums => foobar2000 => Development - (fb2k) => Topic started by: $char(9836) on 2009-09-24 10:54:16

Title: How to use non-static callbacks? (e.g. play_callback)
Post by: $char(9836) on 2009-09-24 10:54:16
I've been studying the SDK and I'm beginning to "get" how things work now.

However I got stuck when trying to register a non-static play_callback. What's is wrong here?
Code: [Select]
// my_play_callback inherits from play_callback_impl_base
service_ptr_t<play_callback> e_ptr = new service_impl_t<my_play_callback>;
//events *e_ptr = new my_play_callback(); // This works, but is unsafe?
static_api_ptr_t<play_callback_manager>()->register_callback(e_ptr,events::flag_on_volume_change,false);


Title: How to use non-static callbacks? (e.g. play_callback)
Post by: Frank Bicking on 2009-09-24 12:53:28
It is difficult to work with such questions when you provide no details on why you are doing this.

Some generic pointers:

play_callback does not inherit from service_base, so you do not need to use service templates.
play_callback_impl_base registers and unregisters itself in its constructor and destructor.
Title: How to use non-static callbacks? (e.g. play_callback)
Post by: $char(9836) on 2009-09-24 15:43:37
I'm just fooling around, trying to implement stuff in the sdk to learn more. The long term goal is a columns ui plugin but that's for later.

In this case I wanted to implement playback callbacks, I figured out static callbacks fine, but wanted to know how to do it dynamically too.

So what autopointer template should I use? Or is it OK to work directly with the pointer as I did in the commented line?

Edit: Typo and missing word.
Title: How to use non-static callbacks? (e.g. play_callback)
Post by: Frank Bicking on 2009-09-24 16:41:05
That really depends on how your callback fits in with the rest of your component.

You typically do not write classes that only implement a non-static callback, and call the registration methods manually. It does not make much sense to do so. Your starting point should be some already existing class, for example, since you mentioned it, an implementation of a user interface window, which you want to react to certain callbacks:

Code: [Select]
class my_window : public ATL::CWindowImpl<my_window>, private play_callback_impl_base
{
private:
    float m_volume;

public:
    my_window() : play_callback_impl_base(play_callback::flag_on_volume_change),
        m_volume(static_api_ptr_t<playback_control>()->get_volume()) {}

private:
    // play_callback
    void on_volume_change(float p_new_val) { m_volume = p_new_val; RedrawWindow(); }

    // CWindowImpl
    BEGIN_MSG_MAP(my_window)
        // Handle drawing messages here to display m_volume.
    END_MSG_MAP()
};

In order to implement a Columns UI panel, my_window would also derive from ui_extension::container_ui_extension, which in turn derives from service_base, and implement whatever methods are required by that interface. my_window would then be registered using ui_extension::window_factory.

As you can see, the callback part is trivial. play_callback_impl_base takes care of registering and unregistering, which automatically happens when your window service is instantiated and deleted, respectively. The play_callback_manager methods only need to receive a raw pointer, since service reference counting ensures the validity of your entire my_window instance.

With this, you should be able to focus on how to implement CUI windows.

Hope this helps.
Title: How to use non-static callbacks? (e.g. play_callback)
Post by: musicmusic on 2009-09-24 17:26:07
Don't inherit from play_callback_impl_base in your uie::window class implementation for a Columns UI panel.

uie::window instances are used in various places including the preferences dialog - you don't want callbacks in those case.

Any such initialisation should instead be done in WM_CREATE/WM_NCCREATE  & WM_DESTROY/WM_NCDESTROY equivalents.
Title: How to use non-static callbacks? (e.g. play_callback)
Post by: Frank Bicking on 2009-09-24 18:02:35
Thanks. It had been a while since I checked the Columns UI SDK.

So, to provide another code snippet for $char(9836), you would inherit your window class from play_callback, and call registration methods in the two message handlers:

Code: [Select]
// WM_CREATE:
static_api_ptr_t<play_callback_manager>()->register_callback(this, play_callback::flag_on_volume_change, false);

// WM_DESTROY:
static_api_ptr_t<play_callback_manager>()->unregister_callback(this);
Title: How to use non-static callbacks? (e.g. play_callback)
Post by: $char(9836) on 2009-09-24 21:01:04
Many thanks for the helpful answers. I get the whole play_callback thing know (actually the entire sdk begins to make sense).

I guess I'll start implementing my columns ui panel now, hopefully the Window programming won't kill me (one could only hope).

Thanks again.