1 /**********
2 This library is free software; you can redistribute it and/or modify it under
3 the terms of the GNU Lesser General Public License as published by the
4 Free Software Foundation; either version 3 of the License, or (at your
5 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6 
7 This library is distributed in the hope that it will be useful, but WITHOUT
8 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
10 more details.
11 
12 You should have received a copy of the GNU Lesser General Public License
13 along with this library; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
15 **********/
16 // "liveMedia"
17 // Copyright (c) 1996-2020 Live Networks, Inc.  All rights reserved.
18 // Media
19 // Implementation
20 
21 #include "Media.hh"
22 #include "HashTable.hh"
23 
24 ////////// Medium //////////
25 
Medium(UsageEnvironment & env)26 Medium::Medium(UsageEnvironment& env)
27 	: fEnviron(env), fNextTask(NULL) {
28   // First generate a name for the new medium:
29   MediaLookupTable::ourMedia(env)->generateNewName(fMediumName, mediumNameMaxLen);
30   env.setResultMsg(fMediumName);
31 
32   // Then add it to our table:
33   MediaLookupTable::ourMedia(env)->addNew(this, fMediumName);
34 }
35 
~Medium()36 Medium::~Medium() {
37   // Remove any tasks that might be pending for us:
38   fEnviron.taskScheduler().unscheduleDelayedTask(fNextTask);
39 }
40 
lookupByName(UsageEnvironment & env,char const * mediumName,Medium * & resultMedium)41 Boolean Medium::lookupByName(UsageEnvironment& env, char const* mediumName,
42 				  Medium*& resultMedium) {
43   resultMedium = MediaLookupTable::ourMedia(env)->lookup(mediumName);
44   if (resultMedium == NULL) {
45     env.setResultMsg("Medium ", mediumName, " does not exist");
46     return False;
47   }
48 
49   return True;
50 }
51 
close(UsageEnvironment & env,char const * name)52 void Medium::close(UsageEnvironment& env, char const* name) {
53   MediaLookupTable::ourMedia(env)->remove(name);
54 }
55 
close(Medium * medium)56 void Medium::close(Medium* medium) {
57   if (medium == NULL) return;
58 
59   close(medium->envir(), medium->name());
60 }
61 
isSource() const62 Boolean Medium::isSource() const {
63   return False; // default implementation
64 }
65 
isSink() const66 Boolean Medium::isSink() const {
67   return False; // default implementation
68 }
69 
isRTCPInstance() const70 Boolean Medium::isRTCPInstance() const {
71   return False; // default implementation
72 }
73 
isRTSPClient() const74 Boolean Medium::isRTSPClient() const {
75   return False; // default implementation
76 }
77 
isRTSPServer() const78 Boolean Medium::isRTSPServer() const {
79   return False; // default implementation
80 }
81 
isMediaSession() const82 Boolean Medium::isMediaSession() const {
83   return False; // default implementation
84 }
85 
isServerMediaSession() const86 Boolean Medium::isServerMediaSession() const {
87   return False; // default implementation
88 }
89 
90 
91 ////////// _Tables implementation //////////
92 
getOurTables(UsageEnvironment & env,Boolean createIfNotPresent)93 _Tables* _Tables::getOurTables(UsageEnvironment& env, Boolean createIfNotPresent) {
94   if (env.liveMediaPriv == NULL && createIfNotPresent) {
95     env.liveMediaPriv = new _Tables(env);
96   }
97   return (_Tables*)(env.liveMediaPriv);
98 }
99 
reclaimIfPossible()100 void _Tables::reclaimIfPossible() {
101   if (mediaTable == NULL && socketTable == NULL) {
102     fEnv.liveMediaPriv = NULL;
103     delete this;
104   }
105 }
106 
_Tables(UsageEnvironment & env)107 _Tables::_Tables(UsageEnvironment& env)
108   : mediaTable(NULL), socketTable(NULL), fEnv(env) {
109 }
110 
~_Tables()111 _Tables::~_Tables() {
112 }
113 
114 
115 ////////// MediaLookupTable implementation //////////
116 
ourMedia(UsageEnvironment & env)117 MediaLookupTable* MediaLookupTable::ourMedia(UsageEnvironment& env) {
118   _Tables* ourTables = _Tables::getOurTables(env);
119   if (ourTables->mediaTable == NULL) {
120     // Create a new table to record the media that are to be created in
121     // this environment:
122     ourTables->mediaTable = new MediaLookupTable(env);
123   }
124   return ourTables->mediaTable;
125 }
126 
lookup(char const * name) const127 Medium* MediaLookupTable::lookup(char const* name) const {
128   return (Medium*)(fTable->Lookup(name));
129 }
130 
addNew(Medium * medium,char * mediumName)131 void MediaLookupTable::addNew(Medium* medium, char* mediumName) {
132   fTable->Add(mediumName, (void*)medium);
133 }
134 
remove(char const * name)135 void MediaLookupTable::remove(char const* name) {
136   Medium* medium = lookup(name);
137   if (medium != NULL) {
138     fTable->Remove(name);
139     if (fTable->IsEmpty()) {
140       // We can also delete ourselves (to reclaim space):
141       _Tables* ourTables = _Tables::getOurTables(fEnv);
142       delete this;
143       ourTables->mediaTable = NULL;
144       ourTables->reclaimIfPossible();
145     }
146 
147     delete medium;
148   }
149 }
150 
generateNewName(char * mediumName,unsigned)151 void MediaLookupTable::generateNewName(char* mediumName,
152 				       unsigned /*maxLen*/) {
153   // We should really use snprintf() here, but not all systems have it
154   sprintf(mediumName, "liveMedia%d", fNameGenerator++);
155 }
156 
MediaLookupTable(UsageEnvironment & env)157 MediaLookupTable::MediaLookupTable(UsageEnvironment& env)
158   : fEnv(env), fTable(HashTable::create(STRING_HASH_KEYS)), fNameGenerator(0) {
159 }
160 
~MediaLookupTable()161 MediaLookupTable::~MediaLookupTable() {
162   delete fTable;
163 }
164