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: learning howto develop foobar plugins? (Read 12359 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

learning howto develop foobar plugins?

Howdy.

I know C quite well, as well as java. I think i can probably understand C++ well enough because of this (or ill just quickly read a tut on the net).

But foobar's plugins use dlls. Which has me a little perplexed.

Can anyone recommend a good tutorial or something to help me understand how to program plugins for foobar ?. I'm aiming to make a little program that will transmit the currently playing song via rs232 to a uP and LCD.

I've already programmed the uP and set up the LCD and they work, no i just gotta get foobar to pass down the info.

Cheers.

learning howto develop foobar plugins?

Reply #1
Can anyone recommend a good tutorial or something to help me understand how to program plugins for foobar ?.
Look at the first (pinned) topic of this forum.

learning howto develop foobar plugins?

Reply #2
cheers for that.

Seems i'll need to learn winAPI to understand a fair bit of that.

also if someone thinks they are really clever.

My LCD responds via a serial connection on COM 5, 8 bits, no parity,1 stop bit. 9600baud.

It currently accepts (maximum 32 characters, airy fairy constant i chose, real max is soon to be 0x39).

The formatting is.

Artist (backspace) Song (tab).

Once it has recieved both it accepts the input and displays it on the screen, and scrolls back and forth if one of the strings is > 16 characters.

learning howto develop foobar plugins?

Reply #3
Quote
I think i can probably understand C++ well enough because of this (or ill just quickly read a tut on the net).


I'd say you might need a working knowledge of C++, due to the heavy usage of object oriented programming that the foobar2000 SDK uses (templates, classes, objects etc...)

learning howto develop foobar plugins?

Reply #4
as well as java.

I've never looked at it because I don't know Java at all, but there is a [a href='index.php?showtopic=55650']Java Foobar wrapper.[/a] If Java provides a standard COM port class, it may be pretty straightforward to do what you're looking to do in Java without too much trouble.

learning howto develop foobar plugins?

Reply #5
i'll have a look in java.

Originally i'm aiming for the ports and baud rates constant, so i don't really need to use any GUI, but it shouldn't be difficult to implement some selectable stuff in java.

Cheers frozen spoon.

learning howto develop foobar plugins?

Reply #6
ack, i forgot about java and port stuff, has been awhile since i delved into trying to get a LPT port working in java.

There is only really a slow java library for linux/sunsparc machines. Discontinued on windows a long time ago.

Back to C++, i geuss lol. Java seems to be great for things that don't have to interface with the outside world in special ways.

I've read through a C tutorial, and i kinda understand the namespaces now, along with templates. Rest of it is just a mix between java and C it seems.

Geuss i'll still have to go figure out winAPI now, i tried that in C a few months ago, very horrible, there's more tutorials for C++ so it might be a bit better this time round.

Got a feeling this plugin might be a long time coming. Unless i just decide to hack in some COM port stuff .

Currently i feel like my best chance at getting this working with what i know, is to playing around with the dsp tutorial without presets. Instead of loading up pieces of the song and playing with them i can just get the song name and send it to a COM port.

learning howto develop foobar plugins?

Reply #7
Hi bojo,
I found a partially implemented win32 com port handling class of mine, perhaps something like this could get you started:

Comport.h
Code: [Select]
#ifndef __COMPORT_H_
#define __COMPORT_H_

typedef unsigned char comportBits;

#undef PARITY_NONE
#undef PARITY_ODD
#undef PARITY_EVEN
#undef PARITY_MARK
#undef PARITY_SPACE
typedef enum { // as xxxPARITY in winbase.h
  PARITY_NONE  = 0x00,
  PARITY_ODD  = 0x01,
  PARITY_EVEN  = 0x02,
  PARITY_MARK  = 0x03,
  PARITY_SPACE = 0x04,
} comportParity;

typedef enum { // as xxxSTOPBIT(S) in winbase.h
  STOP_1  = 0x00,
  STOP_1_5 = 0x01,
  STOP_2  = 0x02
} comportStop;

typedef enum { // as DTR_CONTROL_xxx in winbase.h
  DTR_LOW      = 0x00,
  DTR_HIGH      = 0x01,
  DTR_HANDSHAKE = 0x02
} comportDTR;

typedef enum { // as RTS_CONTROL_xxx in winbase.h
  RTS_LOW      = 0x00,
  RTS_HIGH      = 0x01,
  RTS_HANDSHAKE = 0x02,
  RTS_TOGGLE    = 0x03
} comportRTS;

class ComPort {
  private:
    HANDLE hComHandle;

  protected:
    void init(const char *port, int baudrate, comportBits bits, comportParity parity,
              comportStop stop, comportDTR dtr, comportRTS rts);
  public:
    ComPort(const char *port);
    ComPort(const char *port, int baudrate);
    ComPort(const char *port, int baudrate, comportBits bits, comportParity parity,
            comportStop stop, comportDTR dtr, comportRTS rts);
    ~ComPort();

    void setBaud(int baudrate);
    void setParity(comportParity parity);
    void setBits(comportBits bits);
    void setStop(comportStop stop);
    void setDTR(comportDTR dtr);
    void setRTS(comportRTS cts);
    void txChar(unsigned char byte);
    void txStringN(int len, const char *str);
    void txString(const char *str);
    int rxStatus();
    unsigned char rxChar();
};

#endif

Comport.cpp
Code: [Select]
#include <windows.h>
#include "ComPort.h"

ComPort::ComPort(const char *port)
{
  init(port,9600,8,PARITY_NONE,STOP_2,DTR_HIGH,RTS_HIGH);
}

ComPort::ComPort(const char *port, int baudrate)
{
  init(port,baudrate,8,PARITY_NONE,STOP_2,DTR_HIGH,RTS_HIGH);
}

ComPort::ComPort(const char *port, int baudrate, comportBits bits, comportParity parity,
                comportStop stop, comportDTR dtr, comportRTS rts)
{
  init(port,baudrate,bits,parity,stop,dtr,rts);
}

void ComPort::init(const char *port, int baudrate, comportBits bits, comportParity parity,
                  comportStop stop, comportDTR dtr, comportRTS rts)
{
  if (!port) {
    hComHandle = INVALID_HANDLE_VALUE;
    return;
  }

  char device[MAX_PATH];
  strcpy(device,"\\\\.\\"); strcat(device,port);
  hComHandle = CreateFileA(device,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
  if (hComHandle == INVALID_HANDLE_VALUE)
    throw win32_exception::win32_exception(GetLastError());

  if (!SetupComm(hComHandle,4096,1024)) {
    DWORD err = GetLastError();
    CloseHandle(hComHandle); hComHandle = INVALID_HANDLE_VALUE;
    throw win32_exception::win32_exception(err);
  }

  DCB dcb;
  memset(&dcb,0,sizeof(DCB));
  dcb.DCBlength = sizeof(DCB);
  dcb.BaudRate = baudrate;
  dcb.fBinary = TRUE;
  dcb.fParity = (parity == PARITY_NONE) ? 0 : 1;
  dcb.ByteSize = bits;
  dcb.Parity = parity;
  dcb.StopBits = stop;
  dcb.fDtrControl = dtr;
  dcb.fRtsControl = rts;
  if (!SetCommState(hComHandle,&dcb)) {
    DWORD err = GetLastError();
    CloseHandle(hComHandle); hComHandle = INVALID_HANDLE_VALUE;
    throw win32_exception::win32_exception(err);
  }

  COMMTIMEOUTS ctmo;
  ctmo.ReadIntervalTimeout = 0;
  ctmo.ReadTotalTimeoutMultiplier = 0;
  ctmo.ReadTotalTimeoutConstant = 0;
  ctmo.WriteTotalTimeoutMultiplier = 0;
  ctmo.WriteTotalTimeoutConstant = 0;
  if (!SetCommTimeouts(hComHandle,&ctmo)) {
    DWORD err = GetLastError();
    CloseHandle(hComHandle); hComHandle = INVALID_HANDLE_VALUE;
    throw win32_exception::win32_exception(err);
  }
}

ComPort::~ComPort()
{
  if (hComHandle != INVALID_HANDLE_VALUE)
    CloseHandle(hComHandle);
}

void ComPort::setBaud(int baudrate)
{
  if (hComHandle == INVALID_HANDLE_VALUE)
    return;

  DCB dcb;
  dcb.DCBlength = sizeof(DCB);
  GetCommState(hComHandle,&dcb);
  dcb.BaudRate = baudrate;
  SetCommState(hComHandle,&dcb);
}

void ComPort::setBits(comportBits bits)
{
  if (hComHandle == INVALID_HANDLE_VALUE)
    return;

  DCB dcb;
  dcb.DCBlength = sizeof(DCB);
  GetCommState(hComHandle,&dcb);
  dcb.ByteSize = bits;
  SetCommState(hComHandle,&dcb);
}

void ComPort::setParity(comportParity parity)
{
  if (hComHandle == INVALID_HANDLE_VALUE)
    return;

  DCB dcb;
  dcb.DCBlength = sizeof(DCB);
  GetCommState(hComHandle,&dcb);
  dcb.Parity = parity;
  SetCommState(hComHandle,&dcb);
}

void ComPort::setStop(comportStop stop)
{
  if (hComHandle == INVALID_HANDLE_VALUE)
    return;

  DCB dcb;
  dcb.DCBlength = sizeof(DCB);
  GetCommState(hComHandle,&dcb);
  dcb.StopBits = stop;
  SetCommState(hComHandle,&dcb);
}

void ComPort::setDTR(comportDTR dtr)
{
  if (hComHandle == INVALID_HANDLE_VALUE)
    return;

  DCB dcb;
  dcb.DCBlength = sizeof(DCB);
  GetCommState(hComHandle,&dcb);
  dcb.fDtrControl = dtr;
  SetCommState(hComHandle,&dcb);
}

void ComPort::setRTS(comportRTS rts)
{
  if (hComHandle == INVALID_HANDLE_VALUE)
    return;

  DCB dcb;
  dcb.DCBlength = sizeof(DCB);
  GetCommState(hComHandle,&dcb);
  dcb.fRtsControl = rts;
  SetCommState(hComHandle,&dcb);
}

void ComPort::txChar(unsigned char byte)
{
  if (hComHandle == INVALID_HANDLE_VALUE)
    return;

  DWORD nb;
  WriteFile(hComHandle,&byte,1,&nb,NULL);
}

void ComPort::txStringN(int len, const char *str)
{
  if (hComHandle == INVALID_HANDLE_VALUE)
    return;

  DWORD nb;
  WriteFile(hComHandle,str,len,&nb,NULL);
}

void ComPort::txString(const char *str)
{
  if (hComHandle == INVALID_HANDLE_VALUE)
    return;

  DWORD nb;
  WriteFile(hComHandle,str,strlen(str),&nb,NULL);
}

int ComPort::rxStatus()
{
  if (hComHandle == INVALID_HANDLE_VALUE)
    return 0;

  // TODO: implement
  return 0;
}

unsigned char ComPort::rxChar()
{
  if (hComHandle == INVALID_HANDLE_VALUE)
    return 0;

  // TODO: implement
  return 0;
}

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

class my_initquit : public initquit, public play_callback {
  protected:
    ComPort *m_pComPort;
    static_api_ptr_t<playback_control> m_playbackControl;
    service_ptr_t<titleformat_object> m_titleFormat;

  public:
    // initquit methods
    virtual void on_init()
    {
      m_pComPort = new ComPort("COM5", 9600, 8, PARITY_NONE, STOP_1, DTR_LOW, RTS_LOW);
      static_api_ptr_t<titleformat_compiler>()->compile(m_titleFormat, "$cut(%artist%,32)$char(8)$cut(%title%,32)$char(9)");
      static_api_ptr_t<play_callback_manager>()->register_callback(this,
        flag_on_playback_new_track | flag_on_playback_dynamic_info | flag_on_playback_dynamic_info_track, true);
    }

    virtual void on_quit()
    {
        static_api_ptr_t<play_callback_manager>()->unregister_callback(this);
        delete m_pComPort;
    }

    //---

    void updateTrackTitle()
    {
      pfc::string8_fast str;
      if (!m_playbackControl->playback_format_title(NULL, str, m_titleFormat, NULL, playback_control::display_level_titles))
        str = "---\x08---\x09";
      m_pComPort->txString(str);
    }

    // play_callback methods
    virtual void FB2KAPI on_playback_starting(play_control::t_track_command p_command,bool p_paused) {}
    virtual void FB2KAPI on_playback_new_track(metadb_handle_ptr p_track) { updateTrackTitle(); }
    virtual void FB2KAPI on_playback_stop(play_control::t_stop_reason p_reason) {}
    virtual void FB2KAPI on_playback_seek(double p_time) {}
    virtual void FB2KAPI on_playback_pause(bool p_state) {}
    virtual void FB2KAPI on_playback_edited(metadb_handle_ptr p_track) {}
    virtual void FB2KAPI on_playback_dynamic_info(const file_info & p_info) {}
    virtual void FB2KAPI on_playback_dynamic_info_track(const file_info &p_info) { updateTrackTitle(); }
    virtual void FB2KAPI on_playback_time(double p_time) {}
    virtual void FB2KAPI on_volume_change(float p_new_val) {}
};

static initquit_factory_t<my_initquit> foo0;

DECLARE_COMPONENT_VERSION("component name", "0.0.1", "additional info");

Be warned, I haven't tried to compile this.
Full-quoting makes you scroll past the same junk over and over.

learning howto develop foobar plugins?

Reply #8
Yirkha.

I've read over that, and i must thank you alot!.

I'm fairly sure i've got a better idea on how foobar's plugins work. Most of the tutorials had a lot of info and alot of GUI stuff.

Mainly your foo_gen_whatever.cpp file.

Might take me a little longer to read the in's and outs of your com port stuff, but that's alright.

My aim for the next day or two. Is  to make "the useless foobar plugin". one which can be loaded and exited without errors. but doesn't actually do anything.


This is my idea for my "useless plugin"

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


class useless : public initquit, public play_callback {


public:
// initquit methods
virtual void on_init()
{
}

virtual void on_quit()
{
}

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

static initquit_factory_t<useless> foo0;

DECLARE_COMPONENT_VERSION("useless", "0.0.1", "does nothing");


Does that look about right?. As a side note, how on earth do i use visual studio 2005 express? Eg. say to compile the thing i posted earlier.

I'm kinda used to the whole linux and make side of things. Using VC2005 express, say just putting my files in the same folder doesn't work.

Ack setting up the environment is confusing me much more than the code atm.

learning howto develop foobar plugins?

Reply #9
This is my idea for my "useless plugin"
(codebox)

Does that look about right?.

I don't see any problems in that code, at least on the first sight.

As a side note, how on earth do i use visual studio 2005 express? Eg. say to compile the thing i posted earlier.

I'm kinda used to the whole linux and make side of things. Using VC2005 express, say just putting my files in the same folder doesn't work.

Ack setting up the environment is confusing me much more than the code atm.

I'm not sure if this forum is the right place for this kind of questions, so just briefly: load the solution (.sln file) from fb2k SDK, create a new DLL project, insert your file(s) into it, make it depend on pfc, foobar2000_SDK and foobar2000_component_client projects, build it and it should work, more or less.
If not, look at some buildable example in the SDK and try to mimic its settings.
Full-quoting makes you scroll past the same junk over and over.

learning howto develop foobar plugins?

Reply #10
@bojo:
You have to register your play_callback.
an easy way is(this method can
Code: [Select]
class useless : public initquit, public [b]play_callback_static[/b] {
...
};
....
[b]static service_factory_single_t<useless> foo2;[/b]
,or you can use
Code: [Select]
static_api_ptr_t<play_callback_manager> pcm;
pcm->register_callback(...);
to register your play_callback to take effect
and
Code: [Select]
static_api_ptr_t<play_callback_manager> pcm;
  pcm->unregister_callback(...);
to disable it.

learning howto develop foobar plugins?

Reply #11
does the register_callback need to accept any arguments?.

I've still yet to have the chance to test any of this, Visual C++ 2005 seems to be a horrible yet neccesary demon to conquer in order to accomplish this.

I may have to install a 32 bit XP just for VC++2005 Express.

learning howto develop foobar plugins?

Reply #12
using VC++2k8 (included windows SDK). I've managed to start my crawling.

Cheers guys XD.

learning howto develop foobar plugins?

Reply #13
Yirkha i want to have your babies.

Your code works pretty much fantastic.

VC++ complained about the win32_exceptions you were trying to throw. So for now i've kinda (shamefully) bypassed the exception throwing. I might have to look into win32 exception handling, or even the win32 api.
But it's working wonders with my microprocessor, which is the upside.

--For the people who end up searching and get my woes with vista and the like, i bailed on it. Found my old XP discs and put them back on.

learning howto develop foobar plugins?

Reply #14
Yirkha i want to have your babies.

Your code works pretty much fantastic.

VC++ complained about the win32_exceptions you were trying to throw. So for now i've kinda (shamefully) bypassed the exception throwing. I might have to look into win32 exception handling, or even the win32 api.
But it's working wonders with my microprocessor, which is the upside.

--For the people who end up searching and get my woes with vista and the like, i bailed on it. Found my old XP discs and put them back on.


I'm sorry, it should have been exception_win32(GetLastError()), not win32_exception::win32_exception(...) - it's a handy wrapper over Win32 API error codes made in fb2k. The code was originally controlled by return values, not exceptions.

Anyway, it's great that you have been successful, congratulations!
Full-quoting makes you scroll past the same junk over and over.

learning howto develop foobar plugins?

Reply #15
Howdy again.

I've tried using my plugins on a different pc (same OS but, windows xp service pack 2).

I get this

Failed to load DLL: foo_use.dll
Reason: This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem. 

Even the "useless" app does this. I have a feeling VC might be linking to something the other pc doesn't have?.

Stumped and weird....

EDIT: if your compiling with VC2008 express, and the target machine doesn't have VC2008 express installed. You need to install the VC++2008 runtimes. Heres the linky

http://www.microsoft.com/downloads/thankyo...;displayLang=en

learning howto develop foobar plugins?

Reply #16
Or just use the statically linked version of the VC++ runtime.

learning howto develop foobar plugins?

Reply #17
Hi from newbie.

I've been looking for plugin like this. I tried Yirkhas plugin and when I open foobar it says:

Code: [Select]
Assertion failed!

File:.\service.cpp
Line:8

Expression core_api::are_services_available() && g_api


Does this has something to do with play_callback registering?

learning howto develop foobar plugins?

Reply #18
Some wrong code is presumably being called during loading the DLL, i.e. in constructor of a static object. I didn't look into the SDK when exactly could this happen, but try running fb2k from inside the MSVC IDE as a debugged process, you'll find what's going on from the call stack.
Full-quoting makes you scroll past the same junk over and over.