diff options
author | Chris Xiong <chirs241097@gmail.com> | 2017-10-18 11:40:51 +0800 |
---|---|---|
committer | Chris Xiong <chirs241097@gmail.com> | 2017-10-18 11:40:51 +0800 |
commit | d985112164bd2bfeca0c895abb523d45f0e065bb (patch) | |
tree | 3a44ae92001c2a8cac89eb46fe74248249d6e0ea /doc/APIdoc.md | |
parent | 48dd5f9fb11f0a2e69291271d9140ebcec640117 (diff) | |
download | QMidiPlayer-d985112164bd2bfeca0c895abb523d45f0e065bb.tar.xz |
API changes and crash fixes.
Details in the changelog.
Diffstat (limited to 'doc/APIdoc.md')
-rw-r--r-- | doc/APIdoc.md | 111 |
1 files changed, 86 insertions, 25 deletions
diff --git a/doc/APIdoc.md b/doc/APIdoc.md index be7bbc5..517a0fc 100644 --- a/doc/APIdoc.md +++ b/doc/APIdoc.md @@ -61,10 +61,10 @@ Currently plugins can register handlers for these functionalities: (via `(un)registerEventReaderIntf` and `(un)registerFileReadFinishedHandlerIntf`) - Event handler, when an event is going to be sent by the player (via `(un)registerEventHandlerIntf`) -Functionalities has their own interfaces you need to implement(`qmpVisualizationIntf` and `IMidiFileReader`, respectively), -while hooks uses the universal `IMidiCallBack` interface. Functionalities are discussed later. +Functionalities has their own interfaces you need to implement(`qmpVisualizationIntf` and `qmpFileReader`, respectively), +while hooks uses the universal `ICallBack` interface. Functionalities are discussed later. -When you register a hook, you provide the core with a instance of your class that implements the `IMidiCallBack` interface +When you register a hook, you provide the core with a instance of your class that implements the `ICallBack` interface and your `userdata` to be used when the core is calling the callback. When the callback is called, it will be fed with proper `callerdata` generated by the core and the `userdata` you provided. Type of `callerdata` varies by hooks. Event reader and handler hooks have `SEventCallBackData*` as their `callerdata` while file read finish hook doesn't provide @@ -83,11 +83,11 @@ no such states. For non-checkable functionalities, only show() is called when th The user can arrange functionalities shown on the toolbar and the action menu to their needs. ## 4.2 Visualization -Visualization was once a feature of QMidiPlayer's core. But you can now write your own visualization with the -Visualization interface(`qmpVisualizationIntf`). The methods in this interface should be self-explanatory. +Visualization was once a feature of QMidiPlayer's core. But you can now implement your own visualization +as a normal functionality. The code of the default visualization plugin may offer some additional help. ## 4.3 MIDI File Reader -This is not strictly a "functionality", because its interface IMidiFileReader does not inherit qmpFuncBaseIntf. +This is not strictly a "functionality", because its interface qmpFileReader does not inherit qmpFuncBaseIntf. When the user requests to open a file, the core tries to load the file with registered file readers and accepts the first valid result. Therefore you can implement your own file reader, which may even add eXtended Module support to QMidiPlayer! @@ -96,20 +96,35 @@ eXtended Module support to QMidiPlayer! This is not a functionality either. By implementing the interface qmpMidiOutDevice and registering it, you can add custom MIDI Devices in the built-in MIDI mapper. -# 5. Generic Considerations +# 5. Interacting with the core -1. If you implemented a API that returns a pointer to something, you can forget about the pointer after returning -it. The core will free its memory after it is no longer used. You shouldn't extend the class pointed to because -if you do so, the core will not be able to destruct it correctly. Examples include IMidiFileReader::readFile which -returns a pointer to a CMidiFile class. +Your plugin gets a pointer to the class `qmpPluginAPI` after it is initialized, which is what you should use to +interact with the core. + +This interface provides a wide range of APIs that... +- provide information on the file being played +- get/change the current state of the player +- modify events when a midi file is being read +- register custom interfaces (functionalities, output devices, file readers, handlers and hooks) +- provide options management + + +# 6. General Considerations & Notes + +1. If you implemented a API that returns a pointer to an instance of some nonabstract class, you can forget about +the pointer after returning it. The core will free its memory after it is no longer used. You shouldn't extend the +class pointed to because if you do so, the core will not be able to destruct it correctly. Examples include +qmpFileReader::readFile which returns a pointer to a CMidiFile class. 2. However if you passed a pointer to the core through a function in qmpPluginAPI, you cannot forget about the pointer later. As these pointers are mostly polymorphic, the core cannot handle their destruction. You have to delete them yourself in the deinit() function of your plugin. 3. Do not throw exceptions to the core. The core doesn't handle exceptions and they will crash the entire program. Use the return value to indicate failure of a procedure instead. +4. The core does not handle MIDI running status, nor does it send events to any components with running status either. +That is to say, the `type` parameter found in SEvent and SEventCallBackData should be always greater than or equal to +0x80. -# 6. Reference -Well, everything above is just nonsense compared to this one. The full reference of the API is here. +# 7. Reference ## Structures & Classes @@ -119,7 +134,7 @@ Describes an MIDI event. - `uint32_t iid` internal id. Usually set to the size of the event pool when current event is read. - `uint32_t time` -timestamp of the event in MIDI tick. +_absolute_ timestamp of the event in MIDI tick. - `uint32_t p1` parameter 1 for the midi event. - `uint32_t p2` @@ -145,6 +160,7 @@ A stripped down version of SEvent that is used to pass event data in APIs. ### class `CMidiTrack` Describes a single MIDI track. A MIDI track consists of multiple MIDI events. +The order of events in `eventList` does not matter as long as the timestamps are correct. - `std::vector<SEvent> eventList` Vector of SEvent's. @@ -152,12 +168,14 @@ Vector of SEvent's. Append an event to the end of the event list. - `SEvent& operator[](size_t sub)` Get the reference to the contained event with the given index. +** Check the validity of the index first! This operator doesn't do the check. ** ### class `CMidiFile` Describes a MIDI file. A MIDI file consists of multiple MIDI tracks. - `bool valid` -Is the MIDI file a valid one? +Is the MIDI file a valid one? If your file reader encountered an unrecognised +file, set it to false. - `char* title` Title of the MIDI file. - `char* copyright` @@ -176,30 +194,30 @@ Ticks per quarter note. SMTPE format is not supported by QMidiPlayer. - `~CMidiFile()` Frees memory occupied by the title and copyright string. -### class `IMidiCallBack` +### class `ICallBack` Generic callback function that can be used for hooking the core. -- `IMidiCallBack()` +- `ICallBack()` Default empty constructor. - `virtual void callBack(void* callerdata,void* userdata)=0;` Abstract function of the callback. callerdata is filled by the caller and userdata is set to whatever you asked for when registering the callback. -- `virtual ~IMidiCallBack()` +- `virtual ~ICallBack()` Virtual empty destructor. -### class `IMidiFileReader` +### class `qmpFileReader` MIDI file reader interface. Use this to implement your file importer. -- `IMidiFileReader()` +- `qmpFileReader()` Default empty constructor. -- `virtual ~IMidiFileReader()` +- `virtual ~qmpFileReader()` Virtual empty destructor. - `virtual CMidiFile* readFile(const char* fn)=0` Abstract function to be implemented by the plugin. This function should read file from the given path (fn) and return a -pointer to the resulting CMidiFile structure. You shoudn't handle the -destruction of the resulting structure as the core will handle it. -Read 5.1 for more details. +pointer to the resulting CMidiFile structure. Don't handle the +destruction of the resulting structure as the core will do it. +Read section 5.1 for more details. After reading each event, you should call qmpPluginAPI::callEventReaderCB to invoke event reader callbacks and process their requests. If a file not supported by the reader is provided, this function should @@ -209,9 +227,52 @@ Only called by event reader callbacks. Expected behavior: Sets the discard flag for the last event you have read. If an event has its discard flag set, it shouldn't be pushed into its track. discardCurrentEvent may be called multiple times by different event reader -callbacks. In such case, there's still only one event discarded. +callbacks. In such case, only the current event is discarded. - `virtual void commitEventChange(SEventCallBackData d)=0` Only called by event reader callbacks. Expected behavior: modifies the last event you have read to the provided data. commitEventChange may be called multiple times by different event reader callbacks. In such case, only the last modification to the current event counts. + +### class `qmpFuncBaseIntf` +This is the base class for all QMP functionalities. + +- `qmpFuncBaseIntf()` +Default empty constructor. +- `virtual ~qmpFuncBaseIntf()` +Virtual empty destructor. +- `virtual void show()=0` +Called by the core when the functionality is requested to show up. +- `virtual void close()=0` +Called by the core when the functionality is requested to be closed. +Never called for a functionality whose `checkable` attribute is registered as `false`. + +### class `qmpMidiOutDevice` +Interface for a midi output device. + +- `qmpMidiOutDevice()` +Default empty constructor. +- `virtual ~qmpMidiOutDevice()` +Virtual empty destructor. +- `virtual void deviceInit()=0` +Initializes the device. +- `virtual void deviceDeinit()=0` +Deinitializes the device. +- `virtual void basicMessage(uint8_t type,uint8_t p1,uint8_t p2)=0` +Sends a basic midi message. +Note that the core doesn't make use of running status. +- `virtual void extendedMessage(uint8_t length,const char* data)=0` +Sends an extended message. ("system exclusive message"). +- `virtual void rpnMessage(uint8_t ch,uint16_t type,uint16_t val)=0` +Sends a registered parameter number controller message. +- `virtual void nrpnMessage(uint8_t ch,uint16_t type,uint16_t val)=0` +Sends a non-registered parameter number controller message. +- `virtual void panic(uint8_t ch)=0` +Stops all voices on a channel. +- `virtual void reset(uint8_t ch)=0` +Reset the status of a channel. +- `virtual void onMapped(uint8_t ch,int refcnt)=0` +Called when the device is mapped. `ch` is the channel it is mapped to. +`refcnt` is the number of channels mapped to this device after the remapping. +- `virtual void onUnmapped(uint8_t ch,int refcnt)=0` +Called when the device is mapped. Parameters are the sams as `onMapped()`. |