Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: play_callback causing runtime error (Read 6505 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

play_callback causing runtime error

I'm trying to use the play_callback, but I keep getting a runtime error when I attempt to play a file.

Code: [Select]
class Test_Class : private play_callback {

public:

    // play_callback methods
    virtual void on_playback_new_track(metadb_handle_ptr p_track) {Send_Message();}

    virtual void on_playback_stop(play_control::t_stop_reason reason) {}
    virtual void on_playback_dynamic_info_track(const file_info & p_info) {}
    virtual void on_playback_starting(play_control::t_track_command p_command, bool p_paused) {}
    virtual void on_playback_seek(double p_time) {}
    virtual void on_playback_pause(bool p_state) {}
    virtual void on_playback_edited(metadb_handle_ptr p_track) {}
    virtual void on_playback_dynamic_info(const file_info & p_info) {}
    virtual void on_playback_time(double p_time) {}
    virtual void on_volume_change(float p_new_val) {}

    void Send_Message();

    Test_Class() {

        // Register play callback.
            try {
                static_api_ptr_t<play_callback_manager> pcm;
                pcm->register_callback(this,
                    flag_on_playback_new_track, false);
            }
            catch (const exception_service_not_found &) {
                // play_callback_manager does not exist; something is very wrong.

            }

    }
};
play callback code taken from tutorial.

I create an instance of this class in on_init, and even test that it was constructed properly by calling Test_Class.Send_Message(). Everything works fine (Send_Message is triggered on foobar start up) but when I attempt to play a track I get repeated Runtime errors.

What did I miss?

play_callback causing runtime error

Reply #1
What does your Send_Message() method do?

play_callback causing runtime error

Reply #2
What does your Send_Message() method do?

It calls ShellExecute to run a command line application:
Code: [Select]
void Test_Class::Send_Message()
{
    ShellExecute(NULL, _T("open"), _T("C:\\snarl_command.exe"), _T("/M \"Hello\" \"Hello World!\""), _T("C:\\"), SW_HIDE);
}


I doubt this is a problem because:
1. it ran successfully when I called it in on_init
2. I've tried taking it out completely (removing all calls to it from the play_callback methods and on_init) and still get the same problem

play_callback causing runtime error

Reply #3
When is your Test_Class instance destroyed?

Apparently, you don't intend to destroy it since there is no destructor to unregister the callback. In that case it may be easier to use a play_callback_static:
Code: [Select]
class snarl_play_callback : public play_callback_static {
public:
    /* play_callback methods go here */

    void Send_Message();

    /* The play_callback_manager enumerates play_callback_static services and registers them automatically. We only have to provide the flags indicating which callbacks we want. */
    virtual unsigned get_flags() {
        return flag_on_playback_new_track;
    }
};

static service_factory_single_t<snarl_play_callback> g_play_callback_static_factory;

Note that a play_callback_static may receive playback notifications before on_init() is called. In case you have to initialize something in your component before it can process those notifications, it can be simpler to handle registration and unregistration manually in on_init() and on_quit().

play_callback causing runtime error

Reply #4
You might as well post your initquit class, where you are creating/destroying the Test_Class. From the following paragraph it seems almost like you are creating it in local scope only.
I create an instance of this class in on_init, and even test that it was constructed properly by calling Test_Class.Send_Message(). Everything works fine (Send_Message is triggered on foobar start up) but when I attempt to play a track I get repeated Runtime errors.
Full-quoting makes you scroll past the same junk over and over.

play_callback causing runtime error

Reply #5
Yirkha: already tried that. here's my initquit class:
Code: [Select]
class initquit_Snarl : public initquit {
public:
    virtual void on_init() {
            Test_Class snarl_Messenger;
            snarl_Messenger.Send_Message();
    }

    virtual void on_quit() {
        // Do nothing.
    }
};


foosion:
I can't seem to instantiate your sample class, due to the following:
'int service_base::service_release(void) throw()' : is abstract
'int service_base::service_add_ref(void) throw()' : is abstract

how should these be initialized?

I also tried registering the play_callback manual in on_init by doing
Code: [Select]
Test_Class snarl_Messenger;
static_api_ptr_t<play_callback_manager> pcm;
                pcm->register_callback(snarl_Messenger,
                    flag_on_playback_new_track, false);

but it's telling me flag_on_playback_new_track is undefined. I tried snarl_Messenger.flag_on_playback_new_track, but that too didn't work.

How would I go about registering it manually in on_init?

play_callback causing runtime error

Reply #6
Yirkha: already tried that. here's my initquit class:
Code: [Select]
class initquit_Snarl : public initquit {
public:
    virtual void on_init() {
            Test_Class snarl_Messenger;
            snarl_Messenger.Send_Message();
    }

    virtual void on_quit() {
        // Do nothing.
    }
};
Yes, this is wrong. The class is created and immediately destroyed when the on_init() method ends, because the created instance gets out of scope. Therefore the "this" pointer registered with play_callback_manager is not valid anymore and random junk is called instead of proper callback virtual function. You'd have to create it using "new" operator (and then worry about the right place to "delete" it), or create it as a global, static instance - then that method suggested by foosion is pretty useful and elegant.

foosion:
I can't seem to instantiate your sample class, due to the following:
'int service_base::service_release(void) throw()' : is abstract
'int service_base::service_add_ref(void) throw()' : is abstract

how should these be initialized?
As foosion wrote at the end of his code - as a static global object and proper service factory template:
Code: [Select]
static service_factory_single_t<Test_Class> g_play_callback_static_factory;


I also tried registering the play_callback manual in on_init by doing
Code: [Select]
Test_Class snarl_Messenger;
static_api_ptr_t<play_callback_manager> pcm;
                pcm->register_callback(snarl_Messenger,
                    flag_on_playback_new_track, false);

but it's telling me flag_on_playback_new_track is undefined. I tried snarl_Messenger.flag_on_playback_new_track, but that too didn't work.

How would I go about registering it manually in on_init?
flag_on_playback_new_track is specified in an enum in play_callback, which you are using as base class with "private" data access, therefore it is not accessible outside. play_callback::flag_on_playback_new_track would work. Revising your general C++ knowledge might help or whatever.
Full-quoting makes you scroll past the same junk over and over.

play_callback causing runtime error

Reply #7
Yirkha, thanks for your help. everything is working fine now.

yea, I really should review the basics of c++.. I've actually never really looked at c++ before, but am familiar with c/c# and I thought that developing a component would be a good way to learn c++. hmm, guess that's not exactly true.

play_callback causing runtime error

Reply #8
The foobar SDK makes heavy use of advanced C++ features. There's heavy usage of templates, inheritance, auto-pointers and initialization rules.
It is a rather heavy start into C++, especially since most of the SDK is undocumented and you will have to guess by yourself by looking at the code.

It is of course possible to start learning C++ that way (that's the way I did it ^^), but you will make quite some annoying mistakes that will cost you a lot of time .

play_callback causing runtime error

Reply #9
I agree that learning C++ from examples and the foobar2000 SDK is not very efficient. A book that actually teaches you the concepts in C++ is better suited for this task. Also note that you should forget everything you know about C# when learning C++; they may look similar but they have different semantics.

play_callback causing runtime error

Reply #10
indeed, it is probably not the best starting point and quite different from C#, as I have apparently found out.