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: register for playlist callback (Read 5140 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

register for playlist callback

Hello.

I would like to get history of making playlist in order to analyze human behavior.
So, I want to use below callbacks

# play
# stop
# pause
# seek

# playlist creation
# playlist add
# playlist remove

Inhering play_callback_static class and overriding its member functions, I could use callback functions for (play, stop, pause, seek).

Code: [Select]
#include "../SDK/foobar2000.h"
#include "../helpers/helpers.h"

DECLARE_COMPONENT_VERSION("test","1.0.0","test")

class CPlayback : public play_callback_static
{
public:
    virtual unsigned int get_flags(void)
    {
        return flag_on_playback_new_track | flag_on_playback_seek | flag_on_playback_pause | flag_on_playback_stop;
    }
    
    virtual void on_playback_new_track(metadb_handle_ptr track)
    {
        console::info("new track");
    }
    virtual void on_playback_stop(play_control::t_stop_reason p_reason)
    {
        console::info("stop");
    }

    virtual void on_playback_time(double p_time) {};

    virtual void on_playback_seek(double time)
    {
        console::info("seek");
    }

    virtual void on_playback_starting(play_control::t_track_command p_command,bool p_paused) {}
    virtual void on_playback_pause(bool p_state)
    {
        console::info("pause")
    }

    virtual void on_playback_edited(metadb_handle_ptr track) {}
    virtual void on_playback_dynamic_info(const file_info & p_info) {};
    virtual void on_playback_dynamic_info_track(const file_info & p_info) {};
    virtual void on_volume_change(float p_new_val) {}
};
static play_callback_static_factory_t<CPlayback> pbsf;


Similarly, I inhered playlist_callback_static class and overrode its member functions.

Code: [Select]
class CPlaylist : public playlist_callback_static
{
public:
    virtual unsigned int get_flags(void)
    {
        return flag_on_playlist_created;
    }
    
    virtual void on_playlist_created(t_size p_index, const char *p_name, t_size p_name_len)
    {
        console::info("test");
    }
};


However, in this case, I don't know how to register (i.e. make instance of playlist_callback_static class).
(In the case of play_callback_static class, we can use static "play_callback_static_factory_t" to register.)

Does anyone know how to register?

register for playlist callback

Reply #1
You are supposed to use playlist_callback, not playlist callback static, to register dynamically. There is a static factory for registering and unregistering callback instances dynamically.

For an overengineered example, see my foo_osd source code on Github.

register for playlist callback

Reply #2
Thank you kode54.
I read your foo_osd source code.
I may understand how to register playlist_callback.
Code: [Select]
CPlaylist cplist;
static_api_ptr_t<playlist_manager>()->register_callback( & cplist, cplist.get_flags() );

or
Code: [Select]
static_api_ptr_t<playlist_manager> sapt;
sapt->register_callback( &cplist, cplist.get_flags() );

However I get some errors.

When I use static_api_ptr_t<playlist_manager>()->register_callback( & cplist, cplist.get_flags() );,
- Error: expected an identifier
- Error: expected a ';'
on the "->" operator.

When I use static_api_ptr_t<playlist_manager> sapt; sapt->register_callback( &cplist, cplist.get_flags() );
- Error: this declaration has no storage class or type specifier
- Error: expected a declaration
on "sapt->".

Do you know what is the problem?


My source code is below.

Code: [Select]
#include "../SDK/foobar2000.h"
#include "../helpers/helpers.h"

#include <stdio.h>
#include <time.h>
#include <fstream>

DECLARE_COMPONENT_VERSION("test","1.0.0","test")

std::ofstream fs_play("play_log.txt",std::ios_base::app);
std::ofstream fs_playlist("playlist_log.txt",std::ios_base::app);
class CPlayback : public play_callback_static
{
public:
    virtual unsigned int get_flags(void)
    {
        return flag_on_playback_new_track
            | flag_on_playback_seek
            | flag_on_playback_pause
            | flag_on_playback_stop
            | flag_on_volume_change
            | flag_on_playback_time
            | flag_on_playback_starting;
    }
    
    virtual void on_playback_new_track(metadb_handle_ptr track)
    {
        time_t now = time(NULL);
        fs_play << now << ",new_track," << track->get_path() << std::endl;
    }

    virtual void on_playback_stop(play_control::t_stop_reason p_reason)
    {
        time_t now = time(NULL);
        fs_play << now << ",stop," << p_reason << std::endl;
    }
    virtual void on_playback_time(double p_time)
    {
        time_t now = time(NULL);
        fs_play << now << ",playback_time," << p_time << std::endl;
    }

    virtual void on_playback_seek(double time_seek)
    {
        time_t now = time(NULL);
        fs_play << now << ",seek," << time_seek << std::endl;        
    }

    virtual void on_playback_starting(play_control::t_track_command p_command,bool p_paused)
    {
        time_t now = time(NULL);
        fs_play << now << ",starting," << p_command << "," << p_paused << std::endl;
    }
    
    virtual void on_playback_pause(bool p_state)
    {
        time_t now = time(NULL);
        fs_play << now << ",pause," << p_state << std::endl;
    }

    virtual void on_playback_edited(metadb_handle_ptr track) {}
    virtual void on_playback_dynamic_info(const file_info & p_info) {};
    virtual void on_playback_dynamic_info_track(const file_info & p_info) {};
    
    virtual void on_volume_change(float p_new_val)
    {
        time_t now = time(NULL);
        fs_play << now << ",volume_change," << p_new_val << std::endl;
    }
};
static play_callback_static_factory_t<CPlayback> pbsf;

class CPlaylist : public playlist_callback
{
public:
    virtual unsigned int get_flags(void)
    {
        return flag_on_items_added;
    }

    virtual void on_items_added(t_size p_playlist,t_size p_start, const pfc::list_base_const_t<metadb_handle_ptr> & p_data,const bit_array & p_selection)
    {
        console::info("playlist added");
    }
    virtual void     on_items_reordered (t_size p_playlist, const t_size *p_order, t_size p_count){}
    virtual void     on_items_removing (t_size p_playlist, const bit_array &p_mask, t_size p_old_count, t_size p_new_count){}
    virtual void     on_items_removed (t_size p_playlist, const bit_array &p_mask, t_size p_old_count, t_size p_new_count){}
    virtual void     on_items_selection_change (t_size p_playlist, const bit_array &p_affected, const bit_array &p_state){}
    virtual void     on_item_focus_change (t_size p_playlist, t_size p_from, t_size p_to){}
    virtual void     on_items_modified (t_size p_playlist, const bit_array &p_mask){}
    virtual void     on_items_modified_fromplayback (t_size p_playlist, const bit_array &p_mask, play_control::t_display_level p_level){}
    virtual void     on_items_replaced (t_size p_playlist, const bit_array &p_mask, const pfc::list_base_const_t< t_on_items_replaced_entry > &p_data){}
    virtual void     on_item_ensure_visible (t_size p_playlist, t_size p_idx){}
    virtual void     on_playlist_activate (t_size p_old, t_size p_new){}
    virtual void     on_playlist_created (t_size p_index, const char *p_name, t_size p_name_len){}
    virtual void     on_playlists_reorder (const t_size *p_order, t_size p_count){}
    virtual void     on_playlists_removing (const bit_array &p_mask, t_size p_old_count, t_size p_new_count){}
    virtual void     on_playlists_removed (const bit_array &p_mask, t_size p_old_count, t_size p_new_count){}
    virtual void     on_playlist_renamed (t_size p_index, const char *p_new_name, t_size p_new_name_len){}
    virtual void     on_default_format_changed (){}
    virtual void     on_playback_order_changed (t_size p_new_index){}
    virtual void     on_playlist_locked (t_size p_playlist, bool p_locked){}
};
CPlaylist cplist;
//static_api_ptr_t<playlist_manager>()->register_callback( & cplist, cplist.get_flags() );
//static_api_ptr_t<playlist_manager> sapt;
//sapt->register_callback( &cplist, cplist.get_flags() );

register for playlist callback

Reply #3
You can't use function level declarations at the base scope of the source code. You must declare those register and unregister functions within a function block. Possibly using the initquit service, which is called on GUI startup and shutdown. Or you can register or unregister from other triggered functions.

initquit would be declared as a class with public void init() and quit() functions, and a static initquit_factory_t to register and instantiate it.

register for playlist callback

Reply #4
Using initquit, I could register playlist_callback.
Thank you very much!!

Code: [Select]
class CPlaylist : public playlist_callback
{
public:
    virtual unsigned int get_flags(void)
    {
        return flag_all;
    }

    virtual void on_items_added(t_size p_playlist,t_size p_start, const pfc::list_base_const_t<metadb_handle_ptr> & p_data,const bit_array & p_selection)
    {
        console::info("items_added");
    }
    virtual void     on_items_reordered (t_size p_playlist, const t_size *p_order, t_size p_count)
    {
        console::info("items_reordered");
    }
    virtual void     on_items_removing (t_size p_playlist, const bit_array &p_mask, t_size p_old_count, t_size p_new_count)
    {
        console::info("items_removing");
    }
    virtual void     on_items_removed (t_size p_playlist, const bit_array &p_mask, t_size p_old_count, t_size p_new_count){}
    virtual void     on_items_selection_change (t_size p_playlist, const bit_array &p_affected, const bit_array &p_state){}
    virtual void     on_item_focus_change (t_size p_playlist, t_size p_from, t_size p_to){}
    virtual void     on_items_modified (t_size p_playlist, const bit_array &p_mask){}
    virtual void     on_items_modified_fromplayback (t_size p_playlist, const bit_array &p_mask, play_control::t_display_level p_level){}
    virtual void     on_items_replaced (t_size p_playlist, const bit_array &p_mask, const pfc::list_base_const_t< t_on_items_replaced_entry > &p_data){}
    virtual void     on_item_ensure_visible (t_size p_playlist, t_size p_idx){}
    virtual void     on_playlist_activate (t_size p_old, t_size p_new){}
    virtual void     on_playlist_created (t_size p_index, const char *p_name, t_size p_name_len)
    {
        console::info("playlist_created");
    }
    virtual void     on_playlists_reorder (const t_size *p_order, t_size p_count){}
    virtual void     on_playlists_removing (const bit_array &p_mask, t_size p_old_count, t_size p_new_count){}
    virtual void     on_playlists_removed (const bit_array &p_mask, t_size p_old_count, t_size p_new_count){}
    virtual void     on_playlist_renamed (t_size p_index, const char *p_new_name, t_size p_new_name_len){}
    virtual void     on_default_format_changed (){}
    virtual void     on_playback_order_changed (t_size p_new_index){}
    virtual void     on_playlist_locked (t_size p_playlist, bool p_locked){}
};
CPlaylist cplist;

class initquit_cplist : public initquit
{
public:
    virtual void on_init()
    {
        console::info("on_init");
        static_api_ptr_t<playlist_manager>()->register_callback(&cplist, cplist.get_flags());
    }

    virtual void on_quit()
    {
        console::info("on_quit");
        static_api_ptr_t<playlist_manager>()->unregister_callback(&cplist);
    }
};
static initquit_factory_t<initquit_cplist> iqft;

register for playlist callback

Reply #5
Quick tip. I suggest you limit the scope of your flags. That way, the core won't call your empty callback functions.

register for playlist callback

Reply #6
I see.

I have a question for flags.
If I use below flag, non-empty callback functions in play_callback are not called as I had expected.
However, non-empty callback functions in playlist_callback are still called.
Is this right(, or a bug)?
Code: [Select]
virtual unsigned int get_flags(void)
    {
        return 0;
    }

register for playlist callback

Reply #7
The header for the callback class defines several flags, which you or together. You'll want flag_on_items_added, flag_on_items_reordered, flag_on_items_removing, and flag_on_playlist_created.