1*820dca4dSJohn Scipione/*! 2*820dca4dSJohn Scipione \file MidiEndpoint.h 3*820dca4dSJohn Scipione \ingroup midi2 4*820dca4dSJohn Scipione \brief Defines the Baseclass of all MIDI consumers and producers. 5*820dca4dSJohn Scipione*/ 6*820dca4dSJohn Scipione 7*820dca4dSJohn Scipione 8*820dca4dSJohn Scipione/*! 9*820dca4dSJohn Scipione \class BMidiEndpoint 10*820dca4dSJohn Scipione \ingroup midi2 11*820dca4dSJohn Scipione \brief Base class for all MIDI endpoints. 12*820dca4dSJohn Scipione 13*820dca4dSJohn Scipione BMidiEndpoint is the abstract base class that represents either a 14*820dca4dSJohn Scipione producer or consumer endpoint. It may be used to obtain the state, name, 15*820dca4dSJohn Scipione properties, or system-wide ID of the object. BMidiEndpoint also provides 16*820dca4dSJohn Scipione the ability to change the name and properties of endpoints that were 17*820dca4dSJohn Scipione created locally. 18*820dca4dSJohn Scipione 19*820dca4dSJohn Scipione Remember, you cannot call the destructor of BMidiEndpoint and its 20*820dca4dSJohn Scipione subclasses directly. Endpoint objects are destructed automatically when 21*820dca4dSJohn Scipione their reference count drops to zero. If necessary, the destructor of a 22*820dca4dSJohn Scipione local endpoint first breaks off any connections and Unregister()'s the 23*820dca4dSJohn Scipione endpoint before it is deleted. However, for good style and bonus points 24*820dca4dSJohn Scipione you should really \link BMidiProducer::Disconnect() Disconnect() \endlink 25*820dca4dSJohn Scipione and Unregister() the object yourself and not rely on the destructor to 26*820dca4dSJohn Scipione do this. 27*820dca4dSJohn Scipione*/ 28*820dca4dSJohn Scipione 29*820dca4dSJohn Scipione/*! 30*820dca4dSJohn Scipione \fn const char* BMidiEndpoint::Name() const 31*820dca4dSJohn Scipione \brief Returns the name of the endpoint. 32*820dca4dSJohn Scipione 33*820dca4dSJohn Scipione The function never returns NULL. If you created a local endpoint by 34*820dca4dSJohn Scipione passing a \c NULL name into its constructor (or passing no name, 35*820dca4dSJohn Scipione which is the same thing), then Name() will return an empty string, 36*820dca4dSJohn Scipione not \c NULL. 37*820dca4dSJohn Scipione 38*820dca4dSJohn Scipione \sa SetName() 39*820dca4dSJohn Scipione*/ 40*820dca4dSJohn Scipione 41*820dca4dSJohn Scipione/*! 42*820dca4dSJohn Scipione \fn void BMidiEndpoint::SetName(const char* name) 43*820dca4dSJohn Scipione \brief Changes the name of the endpoint. 44*820dca4dSJohn Scipione 45*820dca4dSJohn Scipione Names don't have to be unique, but it is recommended that you give any 46*820dca4dSJohn Scipione endpoints you publish meaningful and unique names, so users can easily 47*820dca4dSJohn Scipione recognize what each endpoint does. There is no limit to the size of 48*820dca4dSJohn Scipione endpoint names. 49*820dca4dSJohn Scipione 50*820dca4dSJohn Scipione Even though you can call this function on both remote and local objects, 51*820dca4dSJohn Scipione you are only allowed to change the names of local endpoints; SetName() 52*820dca4dSJohn Scipione calls on remote endpoints are ignored. 53*820dca4dSJohn Scipione 54*820dca4dSJohn Scipione \param name The new name. If you pass \c NULL the name won't be changed. 55*820dca4dSJohn Scipione 56*820dca4dSJohn Scipione \sa Name() 57*820dca4dSJohn Scipione*/ 58*820dca4dSJohn Scipione 59*820dca4dSJohn Scipione/*! 60*820dca4dSJohn Scipione \fn int32 BMidiEndpoint::ID() const 61*820dca4dSJohn Scipione \brief Returns the ID of the endpoint 62*820dca4dSJohn Scipione 63*820dca4dSJohn Scipione An ID uniquely identifies an endpoint in the system. The ID is a signed 64*820dca4dSJohn Scipione 32-bit number that is assigned by the Midi Server when the endpoint is 65*820dca4dSJohn Scipione created. (So even if a local endpoint is not published, it still has a 66*820dca4dSJohn Scipione unique ID.) Valid IDs range from 1 to 0x7FFFFFFF, the largest value an 67*820dca4dSJohn Scipione int32 can have. 0 and negative values are <b>not</b> valid IDs. 68*820dca4dSJohn Scipione*/ 69*820dca4dSJohn Scipione 70*820dca4dSJohn Scipione 71*820dca4dSJohn Scipione/*! 72*820dca4dSJohn Scipione \fn bool BMidiEndpoint::IsProducer() const 73*820dca4dSJohn Scipione \brief Determines whether this endpoint is a BMidiProducer 74*820dca4dSJohn Scipione 75*820dca4dSJohn Scipione If it is, you can use a dynamic_cast to convert this object into a 76*820dca4dSJohn Scipione producer: 77*820dca4dSJohn Scipione 78*820dca4dSJohn Scipione\code 79*820dca4dSJohn Scipioneif (endp->IsProducer()) 80*820dca4dSJohn Scipione{ 81*820dca4dSJohn Scipione BMidiProducer* prod = dynamic_cast<BMidiProducer*>(endp); 82*820dca4dSJohn Scipione 83*820dca4dSJohn Scipione .... 84*820dca4dSJohn Scipione 85*820dca4dSJohn Scipione} 86*820dca4dSJohn Scipione\endcode 87*820dca4dSJohn Scipione 88*820dca4dSJohn Scipione*/ 89*820dca4dSJohn Scipione 90*820dca4dSJohn Scipione 91*820dca4dSJohn Scipione/*! 92*820dca4dSJohn Scipione \fn bool BMidiEndpoint::IsConsumer() const 93*820dca4dSJohn Scipione \brief Determines whether this endpoint is a BMidiConsumer 94*820dca4dSJohn Scipione 95*820dca4dSJohn Scipione If it is, you can use a dynamic_cast to convert this object into a consumer: 96*820dca4dSJohn Scipione 97*820dca4dSJohn Scipione\code 98*820dca4dSJohn Scipioneif (endp->IsConsumer()) 99*820dca4dSJohn Scipione{ 100*820dca4dSJohn Scipione BMidiConsumer* cons = dynamic_cast<BMidiConsumer*>(endp); 101*820dca4dSJohn Scipione 102*820dca4dSJohn Scipione .... 103*820dca4dSJohn Scipione 104*820dca4dSJohn Scipione} 105*820dca4dSJohn Scipione\endcode 106*820dca4dSJohn Scipione 107*820dca4dSJohn Scipione*/ 108*820dca4dSJohn Scipione 109*820dca4dSJohn Scipione 110*820dca4dSJohn Scipione/*! 111*820dca4dSJohn Scipione \fn bool BMidiEndpoint::IsRemote() const 112*820dca4dSJohn Scipione \brief Determines whether this endpoint is a proxy for a remote object. 113*820dca4dSJohn Scipione 114*820dca4dSJohn Scipione An endpoint is "remote" when it is created by another application. 115*820dca4dSJohn Scipione Obviously, the remote object is Register()'ed as well, otherwise you would 116*820dca4dSJohn Scipione not be able to see it. 117*820dca4dSJohn Scipione*/ 118*820dca4dSJohn Scipione 119*820dca4dSJohn Scipione 120*820dca4dSJohn Scipione/*! 121*820dca4dSJohn Scipione \fn bool BMidiEndpoint::IsLocal() const 122*820dca4dSJohn Scipione \brief Determines whether this endpoint represents a local object 123*820dca4dSJohn Scipione 124*820dca4dSJohn Scipione An endpoint is "local" when it is created by this application; in other 125*820dca4dSJohn Scipione words, a BMidiLocalConsumer or BMidiLocalProducer. 126*820dca4dSJohn Scipione*/ 127*820dca4dSJohn Scipione 128*820dca4dSJohn Scipione 129*820dca4dSJohn Scipione/*! 130*820dca4dSJohn Scipione \fn bool BMidiEndpoint::IsPersistent() const 131*820dca4dSJohn Scipione \brief Not used. 132*820dca4dSJohn Scipione 133*820dca4dSJohn Scipione The purpose of this function is unclear, and as a result it doesn't do 134*820dca4dSJohn Scipione anything in the Haiku Midi Kit implementation. 135*820dca4dSJohn Scipione 136*820dca4dSJohn Scipione \return \c false always. 137*820dca4dSJohn Scipione*/ 138*820dca4dSJohn Scipione 139*820dca4dSJohn Scipione 140*820dca4dSJohn Scipione/*! 141*820dca4dSJohn Scipione \fn bool BMidiEndpoint::IsValid() const 142*820dca4dSJohn Scipione \brief Determines whether the endpoint still exists. 143*820dca4dSJohn Scipione 144*820dca4dSJohn Scipione Suppose you obtained a proxy object for a remote endpoint by querying the 145*820dca4dSJohn Scipione BMidiRoster. What if the application that published this endpoint quits, 146*820dca4dSJohn Scipione or less drastically, Unregister()'s that endpoint? Even though you still 147*820dca4dSJohn Scipione have a BMidiEndpoint proxy object, the real endpoint no longer exists. 148*820dca4dSJohn Scipione You can use IsValid() to check for this. 149*820dca4dSJohn Scipione 150*820dca4dSJohn Scipione Don't worry, operations on invalid objects, such as GetProperties(), will 151*820dca4dSJohn Scipione return an error code (typically B_ERROR), but not cause a crash. Local 152*820dca4dSJohn Scipione objects are always are considered to be valid, even if you did not 153*820dca4dSJohn Scipione Register() them. (The only time a local endpoint is not valid is when there 154*820dca4dSJohn Scipione was a problem constructing it.) 155*820dca4dSJohn Scipione 156*820dca4dSJohn Scipione If the application that created the remote endpoint crashes, then there is 157*820dca4dSJohn Scipione no guarantee that the Midi Server immediately recognizes this. In that 158*820dca4dSJohn Scipione case, IsValid() may still return true. Eventually, the stale endpoint will 159*820dca4dSJohn Scipione be removed from the roster, though. From then on, IsValid() correctly 160*820dca4dSJohn Scipione returns \c false. 161*820dca4dSJohn Scipione*/ 162*820dca4dSJohn Scipione 163*820dca4dSJohn Scipione 164*820dca4dSJohn Scipione/*! 165*820dca4dSJohn Scipione \fn status_t BMidiEndpoint::Acquire() 166*820dca4dSJohn Scipione \brief Increments the endpoint's reference count 167*820dca4dSJohn Scipione 168*820dca4dSJohn Scipione Each BMidiEndpoint has a reference count associated with it, so that 169*820dca4dSJohn Scipione BMidiRoster can do proper bookkeeping. Acquire() increments this reference 170*820dca4dSJohn Scipione count, and Release() decrements it. Once the count reaches zero, the 171*820dca4dSJohn Scipione endpoint is deleted. 172*820dca4dSJohn Scipione 173*820dca4dSJohn Scipione When you are done with the endpoint, whether local or remote, you should 174*820dca4dSJohn Scipione always Release() it! 175*820dca4dSJohn Scipione 176*820dca4dSJohn Scipione Upon construction, local endpoints start with a reference count of 1. Any 177*820dca4dSJohn Scipione objects you obtain from BMidiRoster using the NextXXX() or FindXXX() 178*820dca4dSJohn Scipione functions have their reference counts incremented in the process. If you 179*820dca4dSJohn Scipione forget to call Release(), the objects won't be properly cleaned up and 180*820dca4dSJohn Scipione you'll make a fool out of yourself. 181*820dca4dSJohn Scipione 182*820dca4dSJohn Scipione After you Release() an object, you are advised not to use it any further. 183*820dca4dSJohn Scipione If you do, your app will probably crash. That also happens if you Release() 184*820dca4dSJohn Scipione an object too many times. 185*820dca4dSJohn Scipione 186*820dca4dSJohn Scipione Typically, you don't need to call Acquire(), unless you have two disparate 187*820dca4dSJohn Scipione parts of your application working with the same endpoint, and you don't 188*820dca4dSJohn Scipione want to have to keep track of who needs to Release() the endpoint. Now you 189*820dca4dSJohn Scipione simply have both of them release it. 190*820dca4dSJohn Scipione 191*820dca4dSJohn Scipione \return Always returns B_OK 192*820dca4dSJohn Scipione 193*820dca4dSJohn Scipione \sa Release() 194*820dca4dSJohn Scipione*/ 195*820dca4dSJohn Scipione 196*820dca4dSJohn Scipione/*! 197*820dca4dSJohn Scipione \fn status_t BMidiEndpoint::Release() 198*820dca4dSJohn Scipione \brief Decrements the endpoint's reference count. 199*820dca4dSJohn Scipione 200*820dca4dSJohn Scipione \return Always returns B_OK 201*820dca4dSJohn Scipione 202*820dca4dSJohn Scipione \sa Acquire() 203*820dca4dSJohn Scipione*/ 204*820dca4dSJohn Scipione 205*820dca4dSJohn Scipione/*! 206*820dca4dSJohn Scipione \fn status_t BMidiEndpoint::Register() 207*820dca4dSJohn Scipione \brief Publishes the endpoint on the roster 208*820dca4dSJohn Scipione 209*820dca4dSJohn Scipione MIDI objects created by an application are invisible to other applications 210*820dca4dSJohn Scipione until they are published. To publish an object use the Register() method. 211*820dca4dSJohn Scipione The corresponding Unregister() method will cause an object to once again 212*820dca4dSJohn Scipione become invisible to remote applications. 213*820dca4dSJohn Scipione 214*820dca4dSJohn Scipione BMidiRoster also has Register() and Unregister() methods. You may also use 215*820dca4dSJohn Scipione those methods to publish or hide your endpoints; both do the same thing. 216*820dca4dSJohn Scipione 217*820dca4dSJohn Scipione Although it is considered bad style, calling Register() on local endpoints 218*820dca4dSJohn Scipione that are already registered won't mess things up. The Midi Server will 219*820dca4dSJohn Scipione simply ignore your request. Likewise for Unregister()'ing more than once. 220*820dca4dSJohn Scipione Attempts to Register() or Unregister() remote endpoints will fail, of 221*820dca4dSJohn Scipione course. 222*820dca4dSJohn Scipione 223*820dca4dSJohn Scipione If you are \link BMidiRoster::StartWatching() watching \endlink, you will 224*820dca4dSJohn Scipione <b>not</b> receive notifications for any local endpoints you register or 225*820dca4dSJohn Scipione unregister. Of course, other applications <I>will</I> be notified about 226*820dca4dSJohn Scipione your endpoints. 227*820dca4dSJohn Scipione 228*820dca4dSJohn Scipione Existing connections will not be broken when an object is unregistered, 229*820dca4dSJohn Scipione but future remote connections will be denied. When objects are destroyed, 230*820dca4dSJohn Scipione they automatically become unregistered. 231*820dca4dSJohn Scipione 232*820dca4dSJohn Scipione \returns B_OK on success, or an error code (typically \c B_ERROR) if 233*820dca4dSJohn Scipione something went wrong. 234*820dca4dSJohn Scipione 235*820dca4dSJohn Scipione \sa Unregister() 236*820dca4dSJohn Scipione*/ 237*820dca4dSJohn Scipione 238*820dca4dSJohn Scipione/*! 239*820dca4dSJohn Scipione \fn status_t BMidiEndpoint::Unregister() 240*820dca4dSJohn Scipione \brief Hides the endpoint from the roster/ 241*820dca4dSJohn Scipione 242*820dca4dSJohn Scipione \sa Register() 243*820dca4dSJohn Scipione*/ 244*820dca4dSJohn Scipione 245*820dca4dSJohn Scipione/*! 246*820dca4dSJohn Scipione \fn status_t BMidiEndpoint::SetProperties(const BMessage* props) 247*820dca4dSJohn Scipione \brief Changes the properties of the endpoint 248*820dca4dSJohn Scipione 249*820dca4dSJohn Scipione Endpoints can have properties, which is any kind of information that 250*820dca4dSJohn Scipione might be useful to associate with a MIDI object. The properties are 251*820dca4dSJohn Scipione stored in a BMessage. 252*820dca4dSJohn Scipione 253*820dca4dSJohn Scipione Usage example: 254*820dca4dSJohn Scipione 255*820dca4dSJohn Scipione\code 256*820dca4dSJohn ScipioneBMessage props; 257*820dca4dSJohn Scipioneif (endpoint->GetProperties(&props) == B_OK) 258*820dca4dSJohn Scipione{ 259*820dca4dSJohn Scipione ...add data to the message... 260*820dca4dSJohn Scipione endpoint->SetProperties(&props); 261*820dca4dSJohn Scipione} 262*820dca4dSJohn Scipione\endcode 263*820dca4dSJohn Scipione 264*820dca4dSJohn Scipione You are only allowed to call SetProperties() on a local object. 265*820dca4dSJohn Scipione 266*820dca4dSJohn Scipione Properties should follow a protocol, so different applications will know 267*820dca4dSJohn Scipione how to read each other's properties. The current protocol is very limited 268*820dca4dSJohn Scipione -- it only allows you to associate icons with your endpoints. Be planned 269*820dca4dSJohn Scipione to publish a more complete protocol that included additional information, 270*820dca4dSJohn Scipione such as vendor/model names, copyright/version info, category, etc., but 271*820dca4dSJohn Scipione they never got around to it. 272*820dca4dSJohn Scipione 273*820dca4dSJohn Scipione <TABLE BORDER="1"> 274*820dca4dSJohn Scipione <TR><TD>property</TD><TD>Vector icon (raw data)</TD></TR> 275*820dca4dSJohn Scipione <TR><TD>field name</TD><TD>"icon"</TD></TR> 276*820dca4dSJohn Scipione <TR><TD>field type</TD><TD>'VICN'</TD></TR> 277*820dca4dSJohn Scipione </TABLE> 278*820dca4dSJohn Scipione 279*820dca4dSJohn Scipione This vector icon is available under Haiku only, and comes as raw data, 280*820dca4dSJohn Scipione not a BBitmap. Before being able to display it, you first must render 281*820dca4dSJohn Scipione the vector icon in the size of your choice. 282*820dca4dSJohn Scipione 283*820dca4dSJohn Scipione <TABLE BORDER="1"> 284*820dca4dSJohn Scipione <TR><TD>property</TD><TD>Large (32x32) icon</TD></TR> 285*820dca4dSJohn Scipione <TR><TD>field name</TD><TD>"be:large_icon"</TD></TR> 286*820dca4dSJohn Scipione <TR><TD>field type</TD><TD>'ICON'</TD></TR> 287*820dca4dSJohn Scipione </TABLE> 288*820dca4dSJohn Scipione 289*820dca4dSJohn Scipione <TABLE BORDER="1"> 290*820dca4dSJohn Scipione <TR><TD>property</TD><TD>Small (16x16) icon</TD></TR> 291*820dca4dSJohn Scipione <TR><TD>field name</TD><TD>"be:mini_icon"</TD></TR> 292*820dca4dSJohn Scipione <TR><TD>field type</TD><TD>'MICN'</TD></TR> 293*820dca4dSJohn Scipione </TABLE> 294*820dca4dSJohn Scipione 295*820dca4dSJohn Scipione The MidiUtil package (downloadable from the OpenBeOS website) contains a 296*820dca4dSJohn Scipione number of convenient functions to associate icons with endpoints, so you 297*820dca4dSJohn Scipione don't have to write that code all over again. 298*820dca4dSJohn Scipione 299*820dca4dSJohn Scipione \sa GetProperties() 300*820dca4dSJohn Scipione*/ 301*820dca4dSJohn Scipione 302*820dca4dSJohn Scipione/*! 303*820dca4dSJohn Scipione \fn status_t BMidiEndpoint::GetProperties(BMessage* props) const 304*820dca4dSJohn Scipione \brief Reads the properties of the endpoint 305*820dca4dSJohn Scipione 306*820dca4dSJohn Scipione Usage example: 307*820dca4dSJohn Scipione 308*820dca4dSJohn Scipione\code 309*820dca4dSJohn ScipioneBMessage props; 310*820dca4dSJohn Scipioneif (endpoint->GetProperties(&props) == B_OK) 311*820dca4dSJohn Scipione{ 312*820dca4dSJohn Scipione ...examine the contents of the message... 313*820dca4dSJohn Scipione} 314*820dca4dSJohn Scipione\endcode 315*820dca4dSJohn Scipione 316*820dca4dSJohn Scipione Note that GetProperties() overwrites the contents of your BMessage. 317*820dca4dSJohn Scipione 318*820dca4dSJohn Scipione \sa SetProperties() 319*820dca4dSJohn Scipione*/ 320