@@ -24,7 +24,6 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S
*/
#include " stdafx.h"
// #include "V41/SnarlInterface.h"
#include " ../../SnarlInterface_V42/SnarlInterface.h"
#include " config.h"
#include < map>
@@ -49,62 +48,45 @@ string8 foobarIcon;
Snarl::V42::SnarlInterface sn42;
string8 snarl_password;
UINT SNARL_GLOBAL_MSG = 0 ;
HWND hwndFooSnarlMsg;
std::map<int ,char *> FSMsgClassDecode;
LONG32 lastClassMsg[4 ] = {0 ,0 ,0 ,0 };
LONG32 lastMsg = 0 ;
int FSLastMsgClass = 0 ;
int FSMsgClassCount = 4 ;
metadb_handle_ptr lastSong;
enum FSMsgClass : int {
Stop = 0 ,
Play,
Pause,
Seek
};
// enum FSMsgAction : int {
// Back = 1,
// Next,
// Stop,
// };
inline char base64_char (unsigned char in)
{
static const char base64_chars[64 ] = {' A' ,' B' ,' C' ,' D' ,' E' ,' F' ,' G' ,' H' ,' I' ,' J' ,' K' ,' L' ,' M' ,' N' ,' O' ,' P' ,
' Q' ,' R' ,' S' ,' T' ,' U' ,' V' ,' W' ,' X' ,' Y' ,' Z' ,' a' ,' b' ,' c' ,' d' ,' e' ,' f' ,
' g' ,' h' ,' i' ,' j' ,' k' ,' l' ,' m' ,' n' ,' o' ,' p' ,' q' ,' r' ,' s' ,' t' ,' u' ,' v' ,
' w' ,' x' ,' y' ,' z' ,' 0' ,' 1' ,' 2' ,' 3' ,' 4' ,' 5' ,' 6' ,' 7' ,' 8' ,' 9' ,' +' ,' /' };
return base64_chars[in];
}
void base64_encode (pfc::string_base & out, const unsigned char * data, unsigned size)
{
out.reset ();
#pragma region Declarations
static void try_register ();
static void try_unregister ();
inline char base64_char (unsigned char in);
void base64_encode (pfc::string_base & out, const unsigned char * data, unsigned size);
#pragma endregion
while (size >= 3 )
{
out.add_byte ( base64_char ( data[0 ] >> 2 ) );
out.add_byte ( base64_char ( ( ( data[0 ] & 3 ) << 4 ) + ( data[1 ] >> 4 ) ) );
out.add_byte ( base64_char ( ( ( data[1 ] & 15 ) << 2 ) + ( data[2 ] >> 6 ) ) );
out.add_byte ( base64_char ( data[2 ] & 63 ) );
data += 3 ;
size -= 3 ;
}
if (size == 2 )
{
out.add_byte ( base64_char ( data[0 ] >> 2 ) );
out.add_byte ( base64_char ( ( ( data[0 ] & 3 ) << 4 ) + ( data[1 ] >> 4 ) ) );
out.add_byte ( base64_char ( ( data[1 ] & 15 ) << 2 ) );
out.add_byte ( ' %' );
}
else if (size == 1 )
{
out.add_byte ( base64_char ( data[0 ] >> 2 ) );
out.add_byte ( base64_char ( ( data[0 ] & 3 ) << 4 ) );
out.add_byte ( ' %' );
out.add_byte ( ' %' );
LPSTR FSClass (int intclass){
switch (intclass){
case FSMsgClass::Play:
return " Play" ;
break ;
case FSMsgClass::Pause:
return " Pause" ;
break ;
case FSMsgClass::Stop:
return " Stop" ;
break ;
case FSMsgClass::Seek:
return " Seek" ;
break ;
}
return " " ;
}
void FSRegisterClass (int intClass){
@@ -117,51 +99,7 @@ void FSRegisterClass(int intClass){
}
}
void try_register ()
{
// Register Foobar2000 with Snarl
service_ptr_t <genrand_service> g_rand = genrand_service::g_create ();
g_rand->seed ( time ( NULL ) );
array_t <unsigned > junk;
junk.set_count ( 4 );
for ( unsigned i = 0 ; i < 4 ; i++ ) junk[ i ] = g_rand->genrand ( ~0 );
base64_encode ( snarl_password, junk.get_ptr (), 16 );
LONG32 ret = sn42.Register (" Foobar2000" , " Foobar2000" , foobarIcon,snarl_password.get_ptr (),hwndFooSnarlMsg, WM_USER);
if (ret > 0 )
{
FSRegisterClass (Play);
FSRegisterClass (Pause);
FSRegisterClass (Stop);
FSRegisterClass (Seek);
}
else
{
if (ret != -Snarl::V42::SnarlEnums::ErrorNotRunning)
{
console::formatter () << " [FooSnarl] Unable to register with Snarl" ;
}
}
}
void try_unregister ()
{
// Unregister foosnarl
LONG32 ret = sn42.ClearClasses ();
if (ret < 0 && ret != -Snarl::V42::SnarlEnums::ErrorNotRunning)
{
console::formatter () << " [FooSnarl] Failed to remove registered classes" ;
}
ret = sn42.Unregister (" Foobar2000" );
if (ret < 0 && ret != -Snarl::V42::SnarlEnums::ErrorNotRunning)
{
console::formatter () << " [FooSnarl] Failed to unregister with Snarl" ;
}
}
#pragma region Callback Window
LRESULT CALLBACK WndProcFooSnarl (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
switch (message)
{
@@ -172,7 +110,7 @@ LRESULT CALLBACK WndProcFooSnarl(HWND hwnd, UINT message, WPARAM wParam, LPARAM
case WM_CLOSE:
DestroyWindow (hwnd);
default :
if (message == ::SNARL_GLOBAL_MSG )
if (message == sn42. Broadcast () )
{
switch (wParam)
{
@@ -232,245 +170,338 @@ LRESULT CALLBACK WndProcFooSnarl(HWND hwnd, UINT message, WPARAM wParam, LPARAM
}
return DefWindowProc (hwnd,message,wParam,lParam);
}
#pragma endregion
class FooSnarl : public initquit , public play_callback {
public:
#pragma region Play Callback
class play_callback_foosnarl : public play_callback {
protected:
void on_playback_event (int alertClass){
static_api_ptr_t <playback_control> pc;
metadb_handle_ptr handle;
string8 format;
service_ptr_t <titleformat_object> script;
string_formatter text;
string snarl_title;
string snarl_msg;
string snarl_icon;
string8 snarl_icon_data;
long snarl_time;
if (pc->get_now_playing (handle)){
lastSong.copy (handle);
} else {
handle.copy (lastSong);
}
// initquit metods
void on_init ()
{
string8 image;
static_api_ptr_t <play_callback_manager> playCBM;
static_api_ptr_t <ui_control> uiMain;
WNDCLASSEX wcex = {0 };
if (handle.is_empty ()) return ;
wcex.cbSize = sizeof (WNDCLASSEX);
wcex.lpfnWndProc = (WNDPROC) WndProcFooSnarl;
wcex.hInstance = core_api::get_my_instance ();
wcex.lpszClassName = _T (" FooSnarlMsg" );
// Process title format string for message body
g_advconfig_string_format.get_static_instance ().get_state (format);
static_api_ptr_t <titleformat_compiler>()->compile_safe (script, format);
pc->playback_format_title_ex (handle, NULL , text, script, NULL , play_control::display_level_titles);
snarl_msg = text.toString ();
FSMsgClassDecode[FSMsgClass::Play] = " Play" ;
FSMsgClassDecode[FSMsgClass::Pause] = " Pause" ;
FSMsgClassDecode[FSMsgClass::Stop] = " Stop" ;
FSMsgClassDecode[FSMsgClass::Seek] = " Seek" ;
// Process title format string for message title
g_advconfig_string_title_format.get_static_instance ().get_state (format);
static_api_ptr_t <titleformat_compiler>()->compile_safe (script, format);
pc->playback_format_title_ex (handle, NULL , text, script, NULL , play_control::display_level_titles);
snarl_title = text.toString ();
RegisterClassEx (&wcex);
// Snippet for testing Message Window failures
// LPTSTR lpszFunction = TEXT("RegisterClassEx");
// LPVOID lpMsgBuf;
// LPVOID lpDisplayBuf;
// DWORD dw = GetLastError();
// FormatMessage(
// FORMAT_MESSAGE_ALLOCATE_BUFFER |
// FORMAT_MESSAGE_FROM_SYSTEM |
// FORMAT_MESSAGE_IGNORE_INSERTS,
// NULL,
// dw,
// MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
// (LPTSTR) &lpMsgBuf,
// 0, NULL );
// // Display the error message and exit the process
// lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
// (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
// StringCchPrintf((LPTSTR)lpDisplayBuf,
// LocalSize(lpDisplayBuf) / sizeof(TCHAR),
// TEXT("%s failed with error %d: %s"),
// lpszFunction, dw, lpMsgBuf);
// MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
// LocalFree(lpMsgBuf);
// LocalFree(lpDisplayBuf);
uGetModuleFileName (NULL , foobarIcon);
foobarIcon += " ,105" ;
::SNARL_GLOBAL_MSG = sn42.Broadcast ();
hwndFooSnarlMsg = CreateWindowEx (0 ,_T (" FooSnarlMsg" ),_T (" FooSnarl Msg" ),0 ,0 ,0 ,0 ,0 ,GetDesktopWindow (),0 ,0 ,0 );
if (hwndFooSnarlMsg == NULL )
{
console::formatter () << " [FooSnarl] Unable to create message window (Error 0x" << pfc::format_int (GetLastError (),0 ,16 ) << " )" ;
metadb_handle_list handle_list;
list_t <GUID> guid_list;
handle_list.add_item (handle);
guid_list.add_item ( album_art_ids::cover_front );
try
{
// Get front cover album art if available
abort_callback_impl moo;
album_art_extractor_instance_v2::ptr art_instance = static_api_ptr_t <album_art_manager_v2>()->open ( handle_list, guid_list, moo );
album_art_data_ptr art = art_instance->query ( album_art_ids::cover_front, moo );
if ( art->get_size () )
{
base64_encode ( snarl_icon_data, art->get_ptr (), art->get_size () );
snarl_icon = " " ;
}
}
catch (...)
{
// Process title format string for message icon location
g_advconfig_icon.get_static_instance ().get_state (format);
static_api_ptr_t <titleformat_compiler>()->compile_safe (script, format);
pc->playback_format_title_ex (handle, NULL , text, script, NULL , play_control::display_level_titles);
snarl_icon = text.toString ();
}
// Test for existance of folder.jpg picture file
/* DWORD attrib = GetFileAttributes(stringcvt::string_os_from_utf8(snarl_icon.get_ptr()));
if((snarl_icon.get_ptr()=="")||(0xFFFFFFFF == attrib)){
snarl_icon = foobarIcon;
}*/
// Get display timeout from user settings. If invalid, send error. Shouldn't happen max and min are set.
snarl_time = (long ) g_advconfig_time.get_static_instance ().get_state_int ();
if ((snarl_time==NULL )||(snarl_time==0 )){
snarl_time = 5 ;
snarl_title = " ERROR" ;
snarl_msg = " Set valid display time in settings" ;
}
// Send Snarl Message
if (FSLastMsgClass != alertClass){
sn42.Hide (sn42.GetLastMsgToken ());
}
FSLastMsgClass = alertClass;
if (sn42.IsVisible (lastClassMsg[alertClass]) == Snarl::V42::SnarlEnums::Success)
{
sn42.Update (lastClassMsg[alertClass], FSClass (alertClass),snarl_title.get_ptr (),snarl_msg.get_ptr (),snarl_time, snarl_icon.get_ptr (),snarl_icon_data.get_ptr (),0 ,0 ,0 ,0 );
}
else
{
LONG32 ret = sn42.Notify (FSClass (alertClass), snarl_title.get_ptr (), snarl_msg.get_ptr (), snarl_time, snarl_icon.get_ptr (), snarl_icon_data.get_ptr (), 0 , 0 , 0 ,0 );
if (ret > 0 )
{
FSAddActions ();
}
lastClassMsg[alertClass] = ret;
}
}
// sn.EZNotify("","HWND",(LPCSTR)hwndFooSnarlMsg,5,0,0,0,0);
// Register Playcallback module
playCBM->register_callback (this ,flag_on_playback_new_track |
/* flag_on_playback_dynamic_info | */
flag_on_playback_dynamic_info_track |
flag_on_playback_pause |
flag_on_playback_stop,true );
LONG32 FSAddActions (){
LONG32 token = sn42.GetLastMsgToken ();
sn42.AddAction (token," Back" ," @1" );
sn42.AddAction (token," Next" ," @2" );
sn42.AddAction (token," Stop" ," @3" );
return 0 ;
}
try_register ();
public:
// play_callback methods
void on_playback_starting (play_control::t_track_command p_command,bool p_paused) {}
void on_playback_new_track (metadb_handle_ptr p_track) {
on_playback_event (FSMsgClass::Play);
}
void on_playback_stop (play_control::t_stop_reason p_reason) {
if (p_reason == play_control::stop_reason_eof || p_reason == play_control::stop_reason_user){
on_playback_event (Stop);
}
}
void on_playback_seek (double p_time) {}
void on_playback_pause (bool p_state) {
if (p_state == true ){
on_playback_event (FSMsgClass::Pause);
} else {
on_playback_event (FSMsgClass::Play);
}
}
void on_playback_edited (metadb_handle_ptr p_track) {}
void on_playback_dynamic_info (const file_info & p_info) {}
void on_playback_dynamic_info_track (const file_info &p_info) {
on_playback_event (FSMsgClass::Play);
}
void on_playback_time (double p_time) {}
void on_volume_change (float p_new_val) {}
};
void on_quit ()
{
// Unregister playcallback
static_api_ptr_t <play_callback_manager>()->unregister_callback (this );
static play_callback_foosnarl pcb_foosnarl;
try_unregister ();
# pragma endregion
lastSong = 0 ;
DestroyWindow (hwndFooSnarlMsg);
UnregisterClass (_T (" FooSnarlMsg" ),core_api::get_my_instance ());
#pragma region InitQuit
class initquit_foosnarl : public initquit {
if ( temp_file.get_length () ) uDeleteFile (temp_file);
}
public:
void on_init ()
{
string8 image;
static_api_ptr_t <ui_control> uiMain;
WNDCLASSEX wcex = {0 };
wcex.cbSize = sizeof (WNDCLASSEX);
wcex.lpfnWndProc = (WNDPROC) WndProcFooSnarl;
wcex.hInstance = core_api::get_my_instance ();
wcex.lpszClassName = _T (" FooSnarlMsg" );
protected:
metadb_handle_ptr lastSong;
string8 temp_file;
void on_playback_event (int alertClass){
static_api_ptr_t <playback_control> pc;
metadb_handle_ptr handle;
string8 format;
service_ptr_t <titleformat_object> script;
string_formatter text;
string snarl_title;
string snarl_msg;
string snarl_icon;
string8 snarl_icon_data;
long snarl_time;
if (pc->get_now_playing (handle)){
lastSong.copy (handle);
} else {
handle.copy (lastSong);
}
FSMsgClassDecode[FSMsgClass::Play] = " Play" ;
FSMsgClassDecode[FSMsgClass::Pause] = " Pause" ;
FSMsgClassDecode[FSMsgClass::Stop] = " Stop" ;
FSMsgClassDecode[FSMsgClass::Seek] = " Seek" ;
if (handle. is_empty ()) return ;
RegisterClassEx (&wcex) ;
// Process title format string for message body
g_advconfig_string_format.get_static_instance ().get_state (format);
static_api_ptr_t <titleformat_compiler>()->compile_safe (script, format);
pc->playback_format_title_ex (handle, NULL , text, script, NULL , play_control::display_level_titles);
snarl_msg = text.toString ();
// Process title format string for message title
g_advconfig_string_title_format.get_static_instance ().get_state (format);
static_api_ptr_t <titleformat_compiler>()->compile_safe (script, format);
pc->playback_format_title_ex (handle, NULL , text, script, NULL , play_control::display_level_titles);
snarl_title = text.toString ();
metadb_handle_list handle_list;
list_t <GUID> guid_list;
handle_list.add_item (handle);
guid_list.add_item ( album_art_ids::cover_front );
try
{
// Get front cover album art if available
abort_callback_impl moo;
album_art_extractor_instance_v2::ptr art_instance = static_api_ptr_t <album_art_manager_v2>()->open ( handle_list, guid_list, moo );
album_art_data_ptr art = art_instance->query ( album_art_ids::cover_front, moo );
if ( art->get_size () )
uGetModuleFileName (NULL , foobarIcon);
foobarIcon += " ,105" ;
hwndFooSnarlMsg = CreateWindowEx (0 ,_T (" FooSnarlMsg" ),_T (" FooSnarl Msg" ),0 ,0 ,0 ,0 ,0 ,GetDesktopWindow (),0 ,0 ,0 );
if (hwndFooSnarlMsg == NULL )
{
base64_encode ( snarl_icon_data, art->get_ptr (), art->get_size () );
snarl_icon = " " ;
console::formatter () << " [FooSnarl] Unable to create message window (Error 0x" << pfc::format_int (GetLastError (),0 ,16 ) << " )" ;
}
try_register ();
}
catch (...)
void on_quit ()
{
// Process title format string for message icon location
g_advconfig_icon. get_static_instance (). get_state (format);
static_api_ptr_t <titleformat_compiler>()-> compile_safe (script, format) ;
pc-> playback_format_title_ex (handle, NULL , text, script, NULL , play_control::display_level_titles );
snarl_icon = text. toString ( );
try_unregister ();
lastSong = 0 ;
DestroyWindow (hwndFooSnarlMsg );
UnregisterClass ( _T ( " FooSnarlMsg " ), core_api::get_my_instance () );
}
// Test for existance of folder.jpg picture file
/* DWORD attrib = GetFileAttributes(stringcvt::string_os_from_utf8(snarl_icon.get_ptr()));
if((snarl_icon.get_ptr()=="")||(0xFFFFFFFF == attrib)){
snarl_icon = foobarIcon;
}*/
// Get display timeout from user settings. If invalid, send error. Shouldn't happen max and min are set.
snarl_time = (long ) g_advconfig_time.get_static_instance ().get_state_int ();
if ((snarl_time==NULL )||(snarl_time==0 )){
snarl_time = 5 ;
snarl_title = " ERROR" ;
snarl_msg = " Set valid display time in settings" ;
};
#pragma endregion
#pragma region Main Menu
class mainmenu_commands_foosnarl : public mainmenu_commands {
virtual t_uint32 get_command_count (){
return 1 ;
}
// Send Snarl Message
if (FSLastMsgClass != alertClass){
sn42.Hide (sn42.GetLastMsgToken ());
virtual GUID get_command (t_uint32 p_index){
// {E8D1828F-1AB8-4AC9-BDDC-F6DBB1456961}
static const GUID guid_foosnarl_main_showplaying = { 0xe8d1828f , 0x1ab8 , 0x4ac9 , { 0xbd , 0xdc , 0xf6 , 0xdb , 0xb1 , 0x45 , 0x69 , 0x61 } };
if (p_index == 0 )
return guid_foosnarl_main_showplaying;
return pfc::guid_null;
}
FSLastMsgClass = alertClass;
if (sn42.IsVisible (lastClassMsg[alertClass]) == Snarl::V42::SnarlEnums::Success)
// Set p_out to the name of the n-th command.
// This name is used to identify the command and determines
// the default position of the command in the menu.
virtual void get_name (t_uint32 p_index, pfc::string_base & p_out){
if (p_index == 0 )
p_out = " Snarl Now Playing" ;
}
// Set p_out to the description for the n-th command.
virtual bool get_description (t_uint32 p_index, pfc::string_base & p_out){
if (p_index == 0 )
p_out = " Snarl Now Playing" ;
else
return false ;
return true ;
}
// Every set of commands needs to declare which group it belongs to.
virtual GUID get_parent (){
// return mainmenu_groups::view;
return guid_foosnarl_mainmenu_maingroup;
}
// Execute n-th command.
virtual void execute (t_uint32 p_index, service_ptr_t <service_base> p_callback){
if (p_index == 0 && core_api::assert_main_thread ()){
// Execute Snarl Command here
metadb_handle_ptr np;
static_api_ptr_t <playback_control>()->get_now_playing (np);
pcb_foosnarl.on_playback_new_track (np);
}
}
};
#pragma endregion
static void try_register ()
{
// Register Playcallback module
static_api_ptr_t <play_callback_manager> playCBM;
playCBM->register_callback (&pcb_foosnarl,play_callback_foosnarl::flag_on_playback_new_track|
/* flag_on_playback_dynamic_info | */
play_callback_foosnarl::flag_on_playback_dynamic_info_track|
play_callback_foosnarl::flag_on_playback_pause|
play_callback_foosnarl::flag_on_playback_stop,true );
// Register Foobar2000 with Snarl
service_ptr_t <genrand_service> g_rand = genrand_service::g_create ();
g_rand->seed ( time ( NULL ) );
array_t <unsigned > junk;
junk.set_count ( 4 );
for ( unsigned i = 0 ; i < 4 ; i++ ) junk[ i ] = g_rand->genrand ( ~0 );
base64_encode ( snarl_password, junk.get_ptr (), 16 );
LONG32 ret = sn42.Register (" Foobar2000" , " Foobar2000" , foobarIcon,snarl_password.get_ptr (),hwndFooSnarlMsg, WM_USER);
if (ret > 0 )
{
sn42.Update (lastClassMsg[alertClass], FSClass (alertClass),snarl_title.get_ptr (),snarl_msg.get_ptr (),snarl_time, snarl_icon.get_ptr (),snarl_icon_data.get_ptr (),0 ,0 ,0 ,0 );
FSRegisterClass (Play);
FSRegisterClass (Pause);
FSRegisterClass (Stop);
FSRegisterClass (Seek);
}
else
{
LONG32 ret = sn42.Notify (FSClass (alertClass), snarl_title.get_ptr (), snarl_msg.get_ptr (), snarl_time, snarl_icon.get_ptr (), snarl_icon_data.get_ptr (), 0 , 0 , 0 ,0 );
if (ret > 0 )
if (ret != -Snarl::V42::SnarlEnums::ErrorNotRunning)
{
FSAddActions () ;
console::formatter () << " [FooSnarl] Unable to register with Snarl " ;
}
lastClassMsg[alertClass] = ret;
}
}
LONG32 FSAddActions (){
LONG32 token = sn42.GetLastMsgToken ();
sn42.AddAction (token," Back" ," @1" );
sn42.AddAction (token," Next" ," @2" );
sn42.AddAction (token," Stop" ," @3" );
return 0 ;
}
static void try_unregister ()
{
// Unregister playcallback
static_api_ptr_t <play_callback_manager>()->unregister_callback (&pcb_foosnarl);
public:
// play_callback methods
void on_playback_starting (play_control::t_track_command p_command,bool p_paused) {}
void on_playback_new_track (metadb_handle_ptr p_track) {
on_playback_event (FSMsgClass::Play);
}
void on_playback_stop (play_control::t_stop_reason p_reason) {
if (p_reason == play_control::stop_reason_eof || p_reason == play_control::stop_reason_user){
on_playback_event (Stop);
// Unregister foosnarl
LONG32 ret = sn42.ClearClasses ();
if (ret < 0 && ret != -Snarl::V42::SnarlEnums::ErrorNotRunning)
{
console::formatter () << " [FooSnarl] Failed to remove registered classes" ;
}
}
void on_playback_seek (double p_time) {}
void on_playback_pause (bool p_state) {
if (p_state == true ){
on_playback_event (FSMsgClass::Pause);
} else {
on_playback_event (FSMsgClass::Play);
ret = sn42.Unregister (" Foobar2000" );
if (ret < 0 && ret != -Snarl::V42::SnarlEnums::ErrorNotRunning)
{
console::formatter () << " [FooSnarl] Failed to unregister with Snarl" ;
}
}
void on_playback_edited (metadb_handle_ptr p_track) {}
void on_playback_dynamic_info (const file_info & p_info) {}
void on_playback_dynamic_info_track (const file_info &p_info) {
on_playback_event (FSMsgClass::Play);
#pragma region Utility Functions
inline char base64_char (unsigned char in)
{
static const char base64_chars[64 ] = {' A' ,' B' ,' C' ,' D' ,' E' ,' F' ,' G' ,' H' ,' I' ,' J' ,' K' ,' L' ,' M' ,' N' ,' O' ,' P' ,
' Q' ,' R' ,' S' ,' T' ,' U' ,' V' ,' W' ,' X' ,' Y' ,' Z' ,' a' ,' b' ,' c' ,' d' ,' e' ,' f' ,
' g' ,' h' ,' i' ,' j' ,' k' ,' l' ,' m' ,' n' ,' o' ,' p' ,' q' ,' r' ,' s' ,' t' ,' u' ,' v' ,
' w' ,' x' ,' y' ,' z' ,' 0' ,' 1' ,' 2' ,' 3' ,' 4' ,' 5' ,' 6' ,' 7' ,' 8' ,' 9' ,' +' ,' /' };
return base64_chars[in];
}
void on_playback_time (double p_time) {}
void on_volume_change (float p_new_val) {}
LPSTR FSClass (int intclass){
switch (intclass){
case FSMsgClass::Play:
return " Play" ;
break ;
case FSMsgClass::Pause:
return " Pause" ;
break ;
case FSMsgClass::Stop:
return " Stop" ;
break ;
case FSMsgClass::Seek:
return " Seek" ;
break ;
void base64_encode (pfc::string_base & out, const unsigned char * data, unsigned size)
{
out.reset ();
while (size >= 3 )
{
out.add_byte ( base64_char ( data[0 ] >> 2 ) );
out.add_byte ( base64_char ( ( ( data[0 ] & 3 ) << 4 ) + ( data[1 ] >> 4 ) ) );
out.add_byte ( base64_char ( ( ( data[1 ] & 15 ) << 2 ) + ( data[2 ] >> 6 ) ) );
out.add_byte ( base64_char ( data[2 ] & 63 ) );
data += 3 ;
size -= 3 ;
}
if (size == 2 )
{
out.add_byte ( base64_char ( data[0 ] >> 2 ) );
out.add_byte ( base64_char ( ( ( data[0 ] & 3 ) << 4 ) + ( data[1 ] >> 4 ) ) );
out.add_byte ( base64_char ( ( data[1 ] & 15 ) << 2 ) );
out.add_byte ( ' %' );
}
else if (size == 1 )
{
out.add_byte ( base64_char ( data[0 ] >> 2 ) );
out.add_byte ( base64_char ( ( data[0 ] & 3 ) << 4 ) );
out.add_byte ( ' %' );
out.add_byte ( ' %' );
}
return " " ;
}
#pragma endregion
};
// Register initquit
static initquit_factory_t < FooSnarl > foo0 ;
// Register initquit, menu
static initquit_factory_t < initquit_foosnarl > foo_snarl_initquit;
static mainmenu_commands_factory_t <mainmenu_commands_foosnarl> foo_snarl_menu;
static mainmenu_group_popup_factory mainmenu_group (guid_foosnarl_mainmenu_maingroup, mainmenu_groups::view,mainmenu_commands::sort_priority_dontcare, " FooSnarl " ) ;