hydrogen 1.1.1
NsmClient Class Reference

Non session manager client implementation. More...

#include <NsmClient.h>

Inheritance diagram for NsmClient:
Object

Public Member Functions

 ~NsmClient ()
 Destructor. More...
 
void sendDirtyState (const bool isDirty)
 Informs the NSM server whether the current H2Core::Song is modified or not. More...
 
void createInitialClient ()
 Actual setup, initialization, and registration of the NSM client. More...
 
void shutdown ()
 Causes the NSM client to not process events anymore. More...
 
- Public Member Functions inherited from Object
 ~Object ()
 destructor More...
 
 Object (const Object &obj)
 copy constructor More...
 
 Object (const char *class_name)
 constructor More...
 
const char * class_name () const
 return the class name More...
 
virtual QString toQString (const QString &sPrefix, bool bShort=true) const
 Formatted string version for debugging purposes. More...
 
void Print (bool bShort=true) const
 Prints content of toQString() via DEBUGLOG. More...
 

Static Public Member Functions

static void create_instance ()
 If __instance equals nullptr, a new NsmClient singleton will be created and stored in it. More...
 
static NsmClientget_instance ()
 
- Static Public Member Functions inherited from Object
static void set_count (bool flag)
 enable/disable class instances counting More...
 
static bool count_active ()
 return true if class instances counting is enabled More...
 
static unsigned objects_count ()
 return the number of objects More...
 
static void write_objects_map_to (std::ostream &out)
 output the full objects map to a given ostream More...
 
static void write_objects_map_to_cerr ()
 output objects map to stderr More...
 
static int bootstrap (Logger *logger, bool count=false)
 must be called before any Object instantiation ! More...
 
static Loggerlogger ()
 return the logger instance More...
 

Data Fields

pthread_t m_NsmThread
 Thread the NSM client will run in. More...
 

Static Public Attributes

static NsmClient__instance = nullptr
 Object holding the current NsmClient singleton. More...
 
- Static Public Attributes inherited from Object
static QString sPrintIndention = " "
 String used to format the debugging string output of some core classes. More...
 

/<tt>drumkit</tt>. In all

Part of OpenCallback() responsible for linking and loading of the drumkit samples.

Upon first invocation of this function in a new project, a symbolic link to the folder containing the samples of the current drumkit will be created in following runs of the session the linked samples will be used over the default ones.

If the session were archived, the symbolic link would had been replaced by a folder containing the samples. In such an occasion the samples located in the folder will be loaded. This ensure portability of Hydrogen within a session regardless of the local drumkits present in the user's home.

Parameters
nameAbsolute path to the session folder.
bCheckLinkageWhether or not the linked drumkit should be verified to correspond to name. If set to none, the drumkit will always be relinked.
QString m_sSessionFolderPath
 Folder all the content of the current session will be stored in. More...
 
nsm_client_tm_pNsm
 Stores the current instance of the NSM client. More...
 
bool m_bUnderSessionManagement
 To determine whether Hydrogen is under Non session management, it is not sufficient to check whether the NSM_URL environmental variable is set but also whether the NSM server did respond to the announce message appropriately. More...
 
static bool bNsmShutdown = false
 Indicates whether the NsmClient::NsmProcessEvent() function should continue processing events. More...
 
bool getUnderSessionManagement () const
 
static void linkDrumkit (const char *name, bool bCheckLinkage)
 
static void printError (const QString &msg)
 Custom function to print a colored error message. More...
 
static void printMessage (const QString &msg)
 Custom function to print a colored message. More...
 
 NsmClient ()
 Private constructor to allow construction only via create_instance(). More...
 
static int OpenCallback (const char *name, const char *displayName, const char *clientID, char **outMsg, void *userData)
 Callback function for the NSM server to tell Hydrogen to open a H2Core::Song. More...
 
static int SaveCallback (char **outMsg, void *userData)
 Callback function for the NSM server to tell Hydrogen to save the current session. More...
 
static void * ProcessEvent (void *data)
 Event handling function of the NSM client. More...
 
static void copyPreferences (const char *name)
 Part of OpenCallback() responsible for copying and loading the preferences. More...
 

Additional Inherited Members

- Static Protected Attributes inherited from Object
static Logger__logger = nullptr
 logger instance pointer More...
 

Detailed Description

Non session manager client implementation.

Non session management (NSM) is the name for both a standard/API allowing for a reproducible, multi-application session handling in Linux systems as well as for the actual application - the non-session-manager - implementing it.

Hydrogen is compliant with the standard, send dirty flag to the NSM server to indicate unsaved changes, and is able to switch between different sessions without restarting the entire application. However, Hydrogen does use several files to store all options the user is able to customize and not all of them are stored inside the folder provided by the NSM server. While the song file will be kept there, both the drumkit and preferences are stored elsewhere. Altering either of them can very well affect the state of the individual session, e.g. by disabling a prior set the per track output option of the JACK driver outside of the session and restarting it. So, be very careful.

Author
Sebastian Moors

Constructor & Destructor Documentation

◆ ~NsmClient()

~NsmClient ( )

Destructor.

◆ NsmClient()

NsmClient ( )
private

Private constructor to allow construction only via create_instance().

Member Function Documentation

◆ copyPreferences()

void copyPreferences ( const char *  name)
staticprivate

Part of OpenCallback() responsible for copying and loading the preferences.

Then it uses H2Core::Preferences::loadPreferences() in combination with H2Core::Filesystem::setPreferencesOverwritePath() to load the configurations specific to the session. If none hydrogen.conf file (see USR_CONFIG) is present in the session folder, the one of the user is used to create one instead. Next, a H2Core::EVENT_UPDATE_PREFERENCES event is created to trigger to ensure the GUI reflects the changes in configuration.

Parameters
nameAbsolute path to the session folder.

◆ create_instance()

void create_instance ( )
static

If __instance equals nullptr, a new NsmClient singleton will be created and stored in it.

It is called in H2Core::Hydrogen::create_instance().

◆ createInitialClient()

void createInitialClient ( )

Actual setup, initialization, and registration of the NSM client.

It create a new NSM client, sets the callback functions nsm_open_cb() and nsm_save_cb(), and registers the newly created client with the NSM server. It also indicates that Hydrogen does support the two NSM options "dirty" and "switch", allowing the server to notice whenever there are unsaved changes and to switch between Songs without restarting the whole application.

This function will performs action if a NSM server is already running. This will be indicated by a set environmental variable called "NSM_URL". However, this is condition is not sufficient and only after receiving a certain response - handled by the NSM API inside the nsm_free() function - to the announce message sent by Hydrogen, the client can truly be considered under session management. This particular state will be indicated by setting m_bUnderSessionManagement to true.

◆ get_instance()

static NsmClient * get_instance ( )
inlinestatic
Returns
a pointer to the current NsmClient singleton stored in __instance.

◆ getUnderSessionManagement()

bool getUnderSessionManagement ( ) const
inline
Returns
m_bUnderSessionManagement

◆ linkDrumkit()

void linkDrumkit ( const char *  name,
bool  bCheckLinkage 
)
static

◆ OpenCallback()

int OpenCallback ( const char *  name,
const char *  displayName,
const char *  clientID,
char **  outMsg,
void *  userData 
)
staticprivate

Callback function for the NSM server to tell Hydrogen to open a H2Core::Song.

This function has two separate purposes:

  1. it is used to load the initial session including its H2Core::Song and to set up the audio driver when started via the NSM server.
  2. It handles the switching between sessions by loading the H2Core::Song, the H2Core::Preferences, and the H2Core::Drumkit of the new session without the need to restart the whole application.

To fulfill the 1. purpose, it is important to know that the core part of H2Core::Hydrogen is already initialized when this function is called, but the GUI isn't. In order to allow for a rewiring of all per track JACK output ports, the H2Core::JackAudioDriver::init() function must register them alongside the main left and right output ports in the very initialization and not at a later stage. Therefore, the starting of the audio driver is prohibited whenever the "NSM_URL" environmental variable is set, H2Core::Hydrogen::setInitialSong() is used to store the loaded H2Core::Song, and H2Core::Hydrogen::restartDrivers() to start the audio driver and - if JACK is chosen - to create all per track output ports right away. In addition, is also calls H2Core::Hydrogen::restartLadspaFX() and H2Core::Sampler::reinitialize_playback_track() to set up the missing core parts of Hydrogen.

In the 2. case of switching between session the function will construct an Action of type "OPEN_SONG" - or "NEW_SONG" if no file exists with the provided file path - triggering MidiActionManager::open_song() or MidiActionManager::new_song().

If the GUI is present, it waits - up to 11 seconds - until the H2Core::Song was asynchronously set by the GUI (as a response to the action). This (regular) procedure is only done if a GUI is present and fully loaded and thus H2Core::Hydrogen::m_GUIState is set to H2Core::Hydrogen::GUIState::ready.

All files and symbolic links will be stored in a folder created by this function and named according to name.

Parameters
nameUnique name corresponding to the current session. A folder using this particular name will be created, which will contain the H2Core::Song - using name appended by ".h2song" as file name -, the local H2Core::Preferences, and a symbolic link to the H2Core::Drumkit in use.
displayNameName the application will be presented with by the NSM server. It is determined in NsmClient::createInitialClient() and set to "Hydrogen".
clientIDUnique prefix also present in name, "nJKUV". It will be stored in H2Core::Preferences::m_sNsmClientId to provide it as a suffix when creating a JACK client in H2Core::JackAudioDriver::init().
outMsgUnused argument. Kept for API compatibility.
userDataUnused argument. Kept for API compatibility.
Returns
  • ERR_OK (0): indicating that everything worked fine.
  • ERR_LAUNCH_FAILED (-4): If no clientID provided, the H2Core::Song corresponding to the file path of a concatenation of name and ".h2song" could not be loaded, or the Action could not be provided to MidiActionManager::handleAction().
  • ERR_NOT_NOW (-8): If the H2Core::Preferences instance was not initialized.
See also
copyPreferences()
linkDrumkit()

◆ printError()

void printError ( const QString &  msg)
static

Custom function to print a colored error message.

Since the OpenCallback() and SaveCallback() functions will be invoked by the NSM server and not by Hydrogen itself, we can not use our usual log macros in there.

Parameters
msgString to print to std::cerr.

◆ printMessage()

void printMessage ( const QString &  msg)
static

Custom function to print a colored message.

Since the OpenCallback() and SaveCallback() functions will be invoked by the NSM server and not by Hydrogen itself, we can not use our usual log macros in there.

Parameters
msgString to print to std::cout.

◆ ProcessEvent()

void * ProcessEvent ( void *  data)
staticprivate

Event handling function of the NSM client.

The event handling can be deactivated by calling NsmClient::shutdown() which is setting bNsmShutdown to true.

Parameters
dataNSM client created in NsmClient::createInitialClient().

◆ SaveCallback()

int SaveCallback ( char **  outMsg,
void *  userData 
)
staticprivate

Callback function for the NSM server to tell Hydrogen to save the current session.

It will construct an Action of type "SAVE_ALL" triggering MidiActionManager::save_all().

Parameters
outMsgUnused argument. Kept for API compatibility.
userDataUnused argument. Kept for API compatibility.
Returns
0 - actually ERR_OK defined in the NSM API - indicating that everything worked fine.

◆ sendDirtyState()

void sendDirtyState ( const bool  isDirty)

Informs the NSM server whether the current H2Core::Song is modified or not.

This function is triggered within H2Core::Song::setIsModified().

Parameters
isDirtytrue, if the current H2Core::Song was modified, and false if it wasn't

◆ shutdown()

void shutdown ( )

Causes the NSM client to not process events anymore.

Sets #NsmShutdown to true.

Field Documentation

◆ __instance

NsmClient * __instance = nullptr
static

Object holding the current NsmClient singleton.

It is initialized with nullptr, set with create_instance(), and accessed with get_instance().

◆ bNsmShutdown

bool bNsmShutdown = false
staticprivate

Indicates whether the NsmClient::NsmProcessEvent() function should continue processing events.

Set to true in NsmClient::shutdown().

◆ m_bUnderSessionManagement

bool m_bUnderSessionManagement
private

To determine whether Hydrogen is under Non session management, it is not sufficient to check whether the NSM_URL environmental variable is set but also whether the NSM server did respond to the announce message appropriately.

Therefore, createInitialClient() has to be called first.

◆ m_NsmThread

pthread_t m_NsmThread

Thread the NSM client will run in.

◆ m_pNsm

nsm_client_t* m_pNsm
private

Stores the current instance of the NSM client.

Used in sendDirtyState() to establish a communication to the NSM server.

◆ m_sSessionFolderPath

QString m_sSessionFolderPath

Folder all the content of the current session will be stored in.

Set at the beginning of each session in NsmClient::OpenCallback().