diff --git a/engine/Channel.cpp b/engine/Channel.cpp index f555d083..54598b77 100644 --- a/engine/Channel.cpp +++ b/engine/Channel.cpp @@ -180,13 +180,7 @@ Channel::~Channel() #endif m_timeout = 0; status("deleted"); - if (m_driver) { - m_driver->lock(); - m_driver->channels().remove(this,false); - m_driver->changed(); - m_driver->unlock(); - m_driver = 0; - } + drop(); } void* Channel::getObject(const String& name) const @@ -204,6 +198,7 @@ void Channel::init() m_driver->lock(); if (m_id.null()) m_id << m_driver->prefix() << m_driver->nextid(); + m_driver->m_total++; m_driver->channels().append(this); m_driver->changed(); m_driver->unlock(); @@ -211,6 +206,17 @@ void Channel::init() DDebug(DebugInfo,"Channel::init() '%s' [%p]",m_id.c_str(),this); } +void Channel::drop() +{ + if (!m_driver) + return; + m_driver->lock(); + m_driver->channels().remove(this,false); + m_driver->changed(); + m_driver->unlock(); + m_driver = 0; +} + void Channel::disconnected(bool final, const char* reason) { if (final) @@ -251,9 +257,11 @@ void Channel::complete(Message& msg, bool minimal) const msg.setParam("peerid",getPeer()->id()); } -Message* Channel::message(const char* name, bool minimal) const +Message* Channel::message(const char* name, bool minimal, bool data) { Message* msg = new Message(name); + if (data) + msg->userData(this); complete(*msg,minimal); return msg; } @@ -550,7 +558,7 @@ bool Module::setDebug(Message& msg, const String& target) Driver::Driver(const char* name, const char* type) : Module(name,type), m_init(false), m_varchan(true), - m_routing(0), m_routed(0), + m_routing(0), m_routed(0), m_total(0), m_nextid(0), m_timeout(0), m_maxroute(0), m_maxchans(0) { @@ -737,6 +745,7 @@ void Driver::genUpdate(Message& msg) { msg.addParam("routed",String(m_routed)); msg.addParam("routing",String(m_routing)); + msg.addParam("total",String(m_total)); msg.addParam("chans",String(m_chans.count())); } @@ -762,6 +771,7 @@ void Driver::statusParams(String& str) Module::statusParams(str); str.append("routed=",",") << m_routed; str << ",routing=" << m_routing; + str << ",total=" << m_total; str << ",chans=" << m_chans.count(); } diff --git a/engine/DataFormat.cpp b/engine/DataFormat.cpp index b7d82fb5..4285fc5d 100644 --- a/engine/DataFormat.cpp +++ b/engine/DataFormat.cpp @@ -74,11 +74,16 @@ using namespace TelEngine; int FormatInfo::guessSamples(int len) const { - if (!dataRate) + if (!(frameTime && frameSize)) return 0; - if (frameSize) - len = frameSize * (len / frameSize); - return len * sampleRate / dataRate; + return (len / frameSize) * sampleRate * (long)frameTime / 1000000; +} + +int FormatInfo::dataRate() const +{ + if (!frameTime) + return 0; + return frameSize * 1000000 / frameTime; } typedef struct _flist { @@ -87,16 +92,17 @@ typedef struct _flist { } flist; static const FormatInfo s_formats[] = { - FormatInfo("slin", 16000), - FormatInfo("alaw", 8000), - FormatInfo("mulaw", 8000), - FormatInfo("gsm", 1650, 33), - FormatInfo("ilbc", 1667, 50), - FormatInfo("speex", 0), - FormatInfo("adpcm", 4000), - FormatInfo("g723", 0), - FormatInfo("g726", 4000), - FormatInfo("g729", 1000, 20), + FormatInfo("slin", 160), + FormatInfo("alaw", 80), + FormatInfo("mulaw", 80), + FormatInfo("gsm", 33, 20000), + FormatInfo("ilbc20", 38, 20000), + FormatInfo("ilbc30", 50, 30000), +// FormatInfo("speex", 0), +// FormatInfo("adpcm", 4000), +// FormatInfo("g723", 0), +// FormatInfo("g726", 4000), +// FormatInfo("g729", 1000, 20), FormatInfo("plain", 0, 0, "text", 0), FormatInfo("raw", 0, 0, "data", 0), }; @@ -119,7 +125,7 @@ const FormatInfo* FormatRepository::getFormat(const String& name) return 0; } -const FormatInfo* FormatRepository::addFormat(const String& name, int drate, int fsize, const String& type, int srate, int nchan) +const FormatInfo* FormatRepository::addFormat(const String& name, int fsize, int ftime, const String& type, int srate, int nchan) { if (name.null() || type.null()) return 0; @@ -127,21 +133,21 @@ const FormatInfo* FormatRepository::addFormat(const String& name, int drate, int const FormatInfo* f = getFormat(name); if (f) { // found by name - check if it exactly matches what we have already - if ((drate != f->dataRate) || - (fsize != f->frameSize) || + if ((fsize != f->frameSize) || + (ftime != f->frameTime) || (srate != f->sampleRate) || (nchan != f->numChannels) || (type != f->type)) { - Debug(DebugWarn,"Tried to register '%s' format '%s' drate=%d fsize=%d srate=%d nchan=%d", - type.c_str(),name.c_str(),drate,fsize,srate,nchan); + Debug(DebugWarn,"Tried to register '%s' format '%s' fsize=%d ftime=%d srate=%d nchan=%d", + type.c_str(),name.c_str(),fsize,ftime,srate,nchan); return 0; } return f; } // not in list - add a new one to the installed formats - Debug(DebugInfo,"Registering '%s' format '%s' drate=%d fsize=%d srate=%d nchan=%d", - type.c_str(),name.c_str(),drate,fsize,srate,nchan); - f = new FormatInfo(::strdup(name),drate,fsize,::strdup(type),srate,nchan); + Debug(DebugInfo,"Registering '%s' format '%s' fsize=%d ftime=%d srate=%d nchan=%d", + type.c_str(),name.c_str(),fsize,ftime,srate,nchan); + f = new FormatInfo(::strdup(name),fsize,ftime,::strdup(type),srate,nchan); flist* l = new flist; l->info = f; l->next = s_flist; diff --git a/modules/gsmcodec.cpp b/modules/gsmcodec.cpp index cf411721..54f3f523 100644 --- a/modules/gsmcodec.cpp +++ b/modules/gsmcodec.cpp @@ -127,7 +127,7 @@ void GsmCodec::Consume(const DataBlock& data, unsigned long timeDelta) GsmPlugin::GsmPlugin() { Output("Loaded module GSM - based on libgsm-%d.%d.%d",GSM_MAJOR,GSM_MINOR,GSM_PATCHLEVEL); - const FormatInfo* f = FormatRepository::addFormat("gsm",1650,33); + const FormatInfo* f = FormatRepository::addFormat("gsm",33,20000); caps[0].src = caps[1].dest = f; caps[0].dest = caps[1].src = FormatRepository::getFormat("slin"); } diff --git a/modules/wavefile.cpp b/modules/wavefile.cpp index c1aa35ea..efe07c2a 100644 --- a/modules/wavefile.cpp +++ b/modules/wavefile.cpp @@ -487,8 +487,8 @@ bool RecordHandler::received(Message &msg) String ml(msg.getValue("maxlen")); unsigned maxlen = ml.toInteger(0); - CallEndpoint *ch = static_cast(msg.userData("CallEndpoint")); - DataEndpoint *de = static_cast(msg.userData("DataEndpoint")); + CallEndpoint *ch = static_cast(msg.userObject("CallEndpoint")); + DataEndpoint *de = static_cast(msg.userObject("DataEndpoint")); if (ch && !de) de = ch->setEndpoint(); diff --git a/modules/ysipchan.cpp b/modules/ysipchan.cpp index 754f4f44..3082f3e4 100644 --- a/modules/ysipchan.cpp +++ b/modules/ysipchan.cpp @@ -633,7 +633,7 @@ bool YateSIPEndPoint::incoming(SIPEvent* e, SIPTransaction* t) void YateSIPEndPoint::invite(SIPEvent* e, SIPTransaction* t) { if (!plugin.canAccept()) { - Debug(DebugWarn,"Dropping call, full or exiting"); + Debug(DebugWarn,"Refusing new SIP call, full or exiting"); t->setResponse(480); return; } diff --git a/yatengine.h b/yatengine.h index 273e274b..bb973c43 100644 --- a/yatengine.h +++ b/yatengine.h @@ -235,14 +235,6 @@ public: inline RefObject* userData() const { return m_data; } - /** - * Get a pointer to a derived class of user data given that class name - * @param name Name of the class we are asking for - * @return Pointer to the requested class or NULL if user object id NULL or doesn't implement it - */ - inline void* userData(const String& name) const - { return m_data ? m_data->getObject(name) : 0; } - /** * Set obscure data associated with the message. * The user data is reference counted to avoid stray pointers. @@ -250,6 +242,14 @@ public: */ void userData(RefObject* data); + /** + * Get a pointer to a derived class of user data given that class name + * @param name Name of the class we are asking for + * @return Pointer to the requested class or NULL if user object id NULL or doesn't implement it + */ + inline void* userObject(const String& name) const + { return m_data ? m_data->getObject(name) : 0; } + /** * Retrive a reference to the creation time of the message. * @return A reference to the Time when the message was created diff --git a/yatephone.h b/yatephone.h index ec456431..3406b3f0 100644 --- a/yatephone.h +++ b/yatephone.h @@ -70,16 +70,16 @@ struct FormatInfo { */ const char* type; - /** - * Data rate in octets/second, 0 for variable - */ - int dataRate; - /** * Frame size in octets/frame, 0 for non-framed formats */ int frameSize; + /** + * Frame time in microseconds, 0 for variable + */ + int frameTime; + /** * Rate in samples/second (audio) or 1e-6 frames/second (video), 0 for unknown */ @@ -97,21 +97,28 @@ struct FormatInfo { */ int guessSamples(int len) const; + /** + * Get the data rate in bytes/s + * @return Data rate or 0 if variable/undefined + */ + int dataRate() const; + /** * Default constructor - used to initialize arrays */ inline FormatInfo() : name(0), type("audio"), - dataRate(0), frameSize(0), + frameSize(0), frameTime(0), sampleRate(8000), numChannels(1) { } /** * Normal constructor */ - inline FormatInfo(const char* _name, int drate, int fsize = 0, const char* _type = "audio", int srate = 8000, int nchan = 1) + inline FormatInfo(const char* _name, int fsize = 0, int ftime = 10000, + const char* _type = "audio", int srate = 8000, int nchan = 1) : name(_name), type(_type), - dataRate(drate), frameSize(fsize), + frameSize(fsize), frameTime(ftime), sampleRate(srate), numChannels(nchan) { } }; @@ -153,15 +160,15 @@ public: /** * Add a new format to the repository * @param name Standard no-blanks lowercase format name - * @param drate Data rate in octets/second, 0 for variable - * @param fsize Frame size in octets/frame, 0 for non-framed formats + * @param fsize Data frame size in octets/frame, 0 for non-framed formats + * @param ftime Data frame duration in microseconds, 0 for variable * @param type Format type: "audio", "video", "text" * @param srate Rate in samples/second (audio) or 1e-6 frames/second (video), 0 for unknown * @param nchan Number of channels, typically 1 * @return Pointer to the format info or NULL if another incompatible * format with the same name was already registered */ - static const FormatInfo* addFormat(const String& name, int drate, int fsize, const String& type = "audio", int srate = 8000, int nchan = 1); + static const FormatInfo* addFormat(const String& name, int fsize, int ftime, const String& type = "audio", int srate = 8000, int nchan = 1); }; /** @@ -1099,9 +1106,10 @@ public: * Create a filled notification message * @param name Name of the message to create * @param minimal Set to true to fill in only a minimum of parameters + * @param data Set the channel as message data * @return A new allocated and parameter filled message */ - Message* message(const char* name, bool minimal = false) const; + Message* message(const char* name, bool minimal = false, bool data = false); /** * Notification on remote ringing @@ -1264,6 +1272,11 @@ protected: */ Channel(Driver& driver, const char* id = 0, bool outgoing = false); + /** + * Remove the channel from the parent driver list + */ + void drop(); + /** * Disconnect notification method. * @param final True if this disconnect was called from the destructor. @@ -1297,6 +1310,7 @@ private: class YATE_API Driver : public Module { friend class Router; + friend class Channel; private: bool m_init; @@ -1305,6 +1319,7 @@ private: ObjList m_chans; int m_routing; int m_routed; + int m_total; unsigned int m_nextid; int m_timeout; int m_maxroute; @@ -1398,6 +1413,13 @@ public: inline int routed() const { return m_routed; } + /** + * Get the total number of calls ever created + * @return Number of channels ever created for this driver + */ + inline int total() const + { return m_total; } + protected: /** * Constructor