1 /* 2 KHOMP generic endpoint/channel library. 3 Copyright (C) 2007-2009 Khomp Ind. & Com. 4 5 The contents of this file are subject to the Mozilla Public License Version 1.1 6 (the "License"); you may not use this file except in compliance with the 7 License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ 8 9 Software distributed under the License is distributed on an "AS IS" basis, 10 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for 11 the specific language governing rights and limitations under the License. 12 13 Alternatively, the contents of this file may be used under the terms of the 14 "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which 15 case the provisions of "LGPL License" are applicable instead of those above. 16 17 If you wish to allow use of your version of this file only under the terms of 18 the LGPL License and not to allow others to use your version of this file under 19 the MPL, indicate your decision by deleting the provisions above and replace them 20 with the notice and other provisions required by the LGPL License. If you do not 21 delete the provisions above, a recipient may use your version of this file under 22 either the MPL or the LGPL License. 23 24 The LGPL header follows below: 25 26 This library is free software; you can redistribute it and/or 27 modify it under the terms of the GNU Lesser General Public 28 License as published by the Free Software Foundation; either 29 version 2.1 of the License, or (at your option) any later version. 30 31 This library is distributed in the hope that it will be useful, 32 but WITHOUT ANY WARRANTY; without even the implied warranty of 33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 34 Lesser General Public License for more details. 35 36 You should have received a copy of the GNU Lesser General Public License 37 along with this library; if not, write to the Free Software Foundation, Inc., 38 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 39 40 */ 41 42 #include <string> 43 #include <stdexcept> 44 45 #include <format.hpp> 46 47 #include <k3l.h> 48 49 /* if using full k3l.h (for softpbx), version already defined. */ 50 #ifndef k3lApiMajorVersion 51 # include <k3lVersion.h> 52 #endif 53 54 #ifdef __GNUC_PREREQ 55 #if __GNUC_PREREQ(4,3) 56 #include <cstring> 57 #endif 58 #endif 59 60 #include <types.hpp> 61 62 #ifndef _K3LAPI_HPP_ 63 #define _K3LAPI_HPP_ 64 65 struct K3LAPITraits 66 { 67 struct invalid_device; 68 struct invalid_channel; 69 struct invalid_link; 70 71 struct invalid_target: public std::runtime_error 72 { 73 friend class invalid_device; 74 friend class invalid_channel; 75 friend class invalid_link; 76 77 const int32 device, object; 78 79 protected: invalid_targetK3LAPITraits::invalid_target80 invalid_target(int32 _device, int32 _object, const std::string & msg) 81 : std::runtime_error(msg), device(_device), object(_object) {}; 82 }; 83 84 struct invalid_device: public invalid_target 85 { invalid_deviceK3LAPITraits::invalid_device86 invalid_device(int32 _device) 87 : invalid_target(_device, -1, STG(FMT("invalid device number '%d'") % _device)) {}; 88 }; 89 90 struct invalid_channel: public invalid_target 91 { invalid_channelK3LAPITraits::invalid_channel92 invalid_channel(int32 _device, int32 _channel) 93 : invalid_target(_device, _channel, STG(FMT("invalid channel number '%d' on device '%d'") % _channel % _device)) {}; 94 }; 95 96 struct invalid_link: public invalid_target 97 { invalid_linkK3LAPITraits::invalid_link98 invalid_link(int32 _device, int32 _link) 99 : invalid_target(_device, _link, STG(FMT("invalid link number '%d' on device '%d'") % _link % _device)) {}; 100 }; 101 }; 102 103 struct K3LAPIBase 104 { 105 /* High level checked object identifier. */ 106 107 struct GenericTarget 108 { 109 typedef enum { DEVICE, CHANNEL, MIXER, LINK } Type; 110 GenericTargetK3LAPIBase::GenericTarget111 GenericTarget(const K3LAPIBase & k3lapi, Type _type, int32 _device, int32 _object) 112 : type(_type), device((unsigned int)_device), object((unsigned int)_object) 113 { 114 switch (_type) 115 { 116 case DEVICE: 117 if (!k3lapi.valid_device(_device)) 118 throw K3LAPITraits::invalid_device(_device); 119 break; 120 121 case CHANNEL: 122 case MIXER: 123 if (!k3lapi.valid_channel(_device, _object)) 124 throw K3LAPITraits::invalid_channel(_device, _object); 125 break; 126 127 case LINK: 128 if (!k3lapi.valid_link(_device, _object)) 129 throw K3LAPITraits::invalid_link(_device, _object); 130 break; 131 } 132 }; 133 134 const Type type; 135 136 const unsigned int device; 137 const unsigned int object; 138 }; 139 140 /* 141 struct LinkTarget : public GenericTarget 142 { 143 LinkTarget(const K3LAPIBase & k3lapi, int32 _device, int32 _object) 144 : GenericTarget(k3lapi, GenericTarget::LINK, _device, _object) {}; 145 }; 146 147 struct ChannelTarget : public GenericTarget 148 { 149 ChannelTarget(const K3LAPIBase & k3lapi, int32 _device, int32 _object) 150 : GenericTarget(k3lapi, GenericTarget::CHANNEL, _device, _object) {}; 151 }; 152 153 */ 154 template < GenericTarget::Type T > 155 struct Target: public GenericTarget 156 { TargetK3LAPIBase::Target157 Target(const K3LAPIBase & k3lapi, int32 _device, int32 _object) 158 : GenericTarget(k3lapi, T, _device, _object) {}; 159 160 // operator const GenericTarget&() const { return static_cast<const GenericTarget &>(*this); }; 161 }; 162 163 /* exceptions */ 164 165 struct start_failed: public std::runtime_error 166 { start_failedK3LAPIBase::start_failed167 start_failed(const char * msg) 168 : std::runtime_error(msg) {}; 169 }; 170 171 struct failed_command 172 { failed_commandK3LAPIBase::failed_command173 failed_command(int32 _code, unsigned short _dev, unsigned short _obj, int32 _rc) 174 : code(_code), dev(_dev), obj(_obj), rc(_rc) {}; 175 176 int32 code; 177 unsigned short dev; 178 unsigned short obj; 179 int32 rc; 180 }; 181 182 struct failed_raw_command 183 { failed_raw_commandK3LAPIBase::failed_raw_command184 failed_raw_command(unsigned short _dev, unsigned short _dsp, int32 _rc) 185 : dev(_dev), dsp(_dsp), rc(_rc) {}; 186 187 unsigned short dev; 188 unsigned short dsp; 189 int32 rc; 190 }; 191 192 struct get_param_failed 193 { get_param_failedK3LAPIBase::get_param_failed194 get_param_failed(std::string _name, int32 _rc) 195 : name(_name), rc((KLibraryStatus)_rc) {}; 196 197 std::string name; 198 KLibraryStatus rc; 199 }; 200 201 /* typedefs essenciais */ 202 203 typedef K3L_DEVICE_CONFIG device_conf_type; 204 typedef K3L_CHANNEL_CONFIG channel_conf_type; 205 typedef K3L_CHANNEL_CONFIG * channel_ptr_conf_type; 206 typedef K3L_LINK_CONFIG link_conf_type; 207 typedef K3L_LINK_CONFIG * link_ptr_conf_type; 208 209 /* constructors/destructors */ 210 211 K3LAPIBase(); ~K3LAPIBaseK3LAPIBase212 virtual ~K3LAPIBase() {}; 213 214 /* (init|final)ialize the whole thing! */ 215 216 void start(void); 217 void stop(void); 218 219 /* verificacao de intervalos */ 220 valid_deviceK3LAPIBase221 inline bool valid_device(int32 dev) const 222 { 223 return (dev >= 0 && dev < ((int32)_device_count)); 224 } 225 valid_channelK3LAPIBase226 inline bool valid_channel(int32 dev, int32 obj) const 227 { 228 return (valid_device(dev) && obj >= 0 && obj < ((int32)_channel_count[dev])); 229 } 230 valid_linkK3LAPIBase231 inline bool valid_link(int32 dev, int32 obj) const 232 { 233 return (valid_device(dev) && obj >= 0 && obj < ((int32)_link_count[dev])); 234 } 235 236 /* envio de comandos para placa (geral) */ 237 238 void raw_command(int32 dev, int32 dsp, std::string & str) const; 239 void raw_command(int32 dev, int32 dsp, const char * cmds, int32 size) const; 240 241 /* obter dados 'cacheados' (geral) */ 242 device_countK3LAPIBase243 inline unsigned int device_count(void) const 244 { 245 return _device_count; 246 } 247 248 /* envio de comandos para placa (sem identificadores) */ 249 250 void mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const; 251 void mixerRecord(int32 dev, KDeviceType type, int32 obj, byte track, KMixerSource src, int32 index) const; 252 void mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const; 253 254 void command (int32 dev, int32 obj, int32 code, std::string & str) const; 255 void command (int32 dev, int32 obj, int32 code, const char * parms = NULL) const; 256 257 258 /* envio de comandos para placa (com identificadores) */ 259 mixerK3LAPIBase260 void mixer(const GenericTarget & tgt, byte track, KMixerSource src, int32 index) const 261 { 262 mixer(tgt.device, tgt.object, track, src, index); 263 } 264 mixerRecordK3LAPIBase265 void mixerRecord(const GenericTarget & tgt, byte track, KMixerSource src, int32 index) const 266 { 267 mixerRecord((int32)tgt.device, _device_type[tgt.device], (int32)tgt.object, track, src, index); 268 } 269 mixerCTbusK3LAPIBase270 void mixerCTbus(const GenericTarget & tgt, byte track, KMixerSource src, int32 index) const 271 { 272 mixerCTbus((int32)tgt.device, (int32)tgt.object, track, src, index); 273 } 274 commandK3LAPIBase275 void command(const GenericTarget & tgt, int32 code, std::string & str) const 276 { 277 command((int32)tgt.device, (int32)tgt.object, code, str); 278 }; 279 commandK3LAPIBase280 void command(const GenericTarget & tgt, int32 code, const char * parms = NULL) const 281 { 282 command((int32)tgt.device, (int32)tgt.object, code, parms); 283 }; 284 285 /* obter dados 'cacheados' (com indentificadores) */ 286 channel_countK3LAPIBase287 inline unsigned int channel_count(const GenericTarget & tgt) const 288 { 289 return _channel_count[tgt.device]; 290 } 291 link_countK3LAPIBase292 inline unsigned int link_count(const GenericTarget & tgt) const 293 { 294 return _link_count[tgt.device]; 295 } 296 device_typeK3LAPIBase297 KDeviceType device_type(const GenericTarget & tgt) const 298 { 299 return _device_type[tgt.device]; 300 } 301 device_configK3LAPIBase302 const K3L_DEVICE_CONFIG & device_config(const GenericTarget & tgt) const 303 { 304 return _device_config[tgt.device]; 305 } 306 channel_configK3LAPIBase307 const K3L_CHANNEL_CONFIG & channel_config(const Target<GenericTarget::CHANNEL> & tgt) const 308 { 309 return _channel_config[tgt.device][tgt.object]; 310 } 311 link_configK3LAPIBase312 const K3L_LINK_CONFIG & link_config(const Target<GenericTarget::LINK> & tgt) const 313 { 314 return _link_config[tgt.device][tgt.object]; 315 } 316 317 /* pega valores em strings de eventos */ 318 319 KLibraryStatus get_param(K3L_EVENT *ev, const char *name, std::string &res) const; 320 321 std::string get_param(K3L_EVENT *ev, const char *name) const; 322 std::string get_param_optional(K3L_EVENT *ev, const char *name) const; 323 324 /* inicializa valores em cache */ 325 326 void init(void); 327 void fini(void); 328 329 /* utilidades diversas e informacoes */ 330 331 enum DspType 332 { 333 DSP_AUDIO, 334 DSP_SIGNALING, 335 }; 336 337 int32 get_dsp(KDeviceType, DspType) const; 338 339 int32 get_dsp(const GenericTarget &, DspType) const; 340 341 protected: 342 343 unsigned int _device_count; 344 unsigned int * _channel_count; 345 unsigned int * _link_count; 346 347 device_conf_type * _device_config; 348 channel_ptr_conf_type * _channel_config; 349 link_ptr_conf_type * _link_config; 350 KDeviceType * _device_type; 351 }; 352 353 /* exceptions */ 354 template < bool E = false > 355 struct K3LAPIException 356 { invalid_deviceK3LAPIException357 void invalid_device(const int32 device) const 358 { 359 /* NOTHING */ 360 } 361 invalid_channelK3LAPIException362 void invalid_channel(const int32 device, const int32 channel) const 363 { 364 /* NOTHING */ 365 } 366 invalid_linkK3LAPIException367 void invalid_link(const int32 device, const int32 link) const 368 { 369 /* NOTHING */ 370 } 371 }; 372 373 template < > 374 struct K3LAPIException < true > 375 { invalid_deviceK3LAPIException376 void invalid_device(const int32 device) const 377 { 378 throw K3LAPITraits::invalid_device(device); 379 } 380 invalid_channelK3LAPIException381 void invalid_channel(const int32 device, const int32 channel) const 382 { 383 throw K3LAPITraits::invalid_channel(device, channel); 384 } 385 invalid_linkK3LAPIException386 void invalid_link(const int32 device, const int32 link) const 387 { 388 throw K3LAPITraits::invalid_link(device, link); 389 } 390 }; 391 392 template < bool E = false > 393 struct K3LAPITemplate: public K3LAPIBase, protected K3LAPIException < E > 394 { 395 using K3LAPIBase::device_config; 396 using K3LAPIBase::channel_config; 397 using K3LAPIBase::link_config; 398 399 using K3LAPIBase::device_type; 400 using K3LAPIBase::get_dsp; 401 402 using K3LAPIBase::mixerRecord; 403 404 /* obter dados 'cacheados' (sem identificadores) */ 405 channel_countK3LAPITemplate406 inline unsigned int channel_count(int32 dev) const 407 { 408 if (!valid_device(dev)) 409 { 410 K3LAPIException< E >::invalid_device(dev); 411 return 0; 412 } 413 414 return _channel_count[dev]; 415 } 416 link_countK3LAPITemplate417 inline unsigned int link_count(int32 dev) const 418 { 419 if (!valid_device(dev)) 420 { 421 K3LAPIException< E >::invalid_device(dev); 422 return 0; 423 } 424 425 return _link_count[dev]; 426 } 427 channel_statsK3LAPITemplate428 inline uint32 channel_stats(int32 dev, int32 obj, uint32 index) const 429 { 430 if (!valid_channel(dev, obj)) 431 { 432 K3LAPIException< E >::invalid_channel(dev, obj); 433 return 0u; 434 } 435 436 uint32 res_value = 0u; 437 438 #if K3L_AT_LEAST(2,1,0) 439 if (k3lGetChannelStats(dev, obj, index, &res_value) != ksSuccess) 440 return 0u; 441 442 return res_value; 443 #endif 444 } 445 device_typeK3LAPITemplate446 KDeviceType device_type(int32 dev) const 447 { 448 if (!valid_device(dev)) 449 { 450 K3LAPIException< E >::invalid_device(dev); 451 return kdtDevTypeCount; 452 } 453 454 return _device_type[dev]; 455 } 456 device_configK3LAPITemplate457 const K3L_DEVICE_CONFIG & device_config(int32 dev) const 458 { 459 if (!valid_device(dev)) 460 throw K3LAPITraits::invalid_device(dev); 461 462 return _device_config[dev]; 463 } 464 channel_configK3LAPITemplate465 const K3L_CHANNEL_CONFIG & channel_config(int32 dev, int32 obj) const 466 { 467 if (!valid_channel(dev, obj)) 468 throw K3LAPITraits::invalid_channel(dev, obj); 469 470 return _channel_config[dev][obj]; 471 } 472 link_configK3LAPITemplate473 const K3L_LINK_CONFIG & link_config(int32 dev, int32 obj) const 474 { 475 if (!valid_link(dev, obj)) 476 throw K3LAPITraits::invalid_link(dev, obj); 477 478 return _link_config[dev][obj]; 479 } 480 get_dspK3LAPITemplate481 int32 get_dsp(int32 dev, DspType type) const 482 { 483 return get_dsp(device_type(dev), type); 484 } 485 mixerRecordK3LAPITemplate486 void mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const 487 { 488 mixerRecord(dev, device_type(dev), obj, track, src, index); 489 } 490 }; 491 492 typedef K3LAPITemplate<> K3LAPI; 493 494 #endif /* _K3LAPI_HPP_ */ 495