Statistics
| Branch: | Tag: | Revision:

hlrc / server / src / Arbiter.cpp @ 16a22a2b

History | View | Annotate | Download (9.658 KB)

1
/*
2
* This file is part of hlrc_server
3
*
4
* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
5
* http://opensource.cit-ec.de/projects/hlrc_server
6
*
7
* This file may be licensed under the terms of the
8
* GNU General Public License Version 3 (the ``GPL''),
9
* or (at your option) any later version.
10
*
11
* Software distributed under the License is distributed
12
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13
* express or implied. See the GPL for the specific language
14
* governing rights and limitations.
15
*
16
* You should have received a copy of the GPL along with this
17
* program. If not, go to http://www.gnu.org/licenses/gpl.html
18
* or write to the Free Software Foundation, Inc.,
19
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
*
21
* The development of this software was supported by the
22
* Excellence Cluster EXC 277 Cognitive Interaction Technology.
23
* The Excellence Cluster EXC 277 is a grant of the Deutsche
24
* Forschungsgemeinschaft (DFG) in the context of the German
25
* Excellence Initiative.
26
*
27
*/
28

    
29
#include "Arbiter.h"
30
#include "AudioPlayerLibAO.h"
31
#include "AudioPlayerRSB.h"
32
#include <boost/algorithm/string/predicate.hpp>
33

    
34
using namespace boost;
35
using namespace std;
36

    
37

    
38
Arbiter::Arbiter(std::string audio_output){
39
    //initialize audio player:
40
    if (iequals(audio_output, "none")){
41
        //allow none for no sound output
42
        audio_player = NULL;
43
    }else if (iequals(audio_output.substr(0,3), "rsb")){
44
        #ifdef RSB_SUPPORT
45
            audio_player = new AudioPlayerRSB(audio_output);
46
        #else
47
            printf("> ERROR: hlc is compiled without RSB support, RSB audio transport not available, defaulting to libao (default output!)\n");
48
            audio_player = new AudioPlayerLibAO("");
49
        #endif
50
    }else{
51
        audio_player = new AudioPlayerLibAO(audio_output);
52
    }
53

    
54
    //set default emotion:
55
    emotion_config_current.init_sad();
56
    emotion_config_current.set_duration(2000);
57
    emotion_config_default.init_neutral();
58

    
59
    utterance = boost::shared_ptr<Utterance>(new Utterance());
60
}
61

    
62
Arbiter::~Arbiter(){
63
}
64

    
65
void Arbiter::set_default_emotion(EmotionState e){
66
    //lock access
67
    mutex::scoped_lock scoped_lock(emotion_config_default_mutex);
68

    
69
    //update our config, ignore duration as this is the default emotion
70
    emotion_config_default.select_config(e.value);
71

    
72
    printf("> stored default emotion\n");
73
}
74

    
75
void Arbiter::set_current_emotion(EmotionState e){
76
    //lock access
77
    mutex::scoped_lock scoped_lock(emotion_config_current_mutex);
78

    
79
    //this will set a emotion override for a given time, after the timeout
80
    //we will return to the default emotion state:
81
    emotion_config_current.select_config(e.value);
82
    emotion_config_current.set_duration(e.duration);
83

    
84
    printf("> stored current emotion (val=%d, duration = %dms)\n",e.value, e.duration);
85
}
86

    
87
void Arbiter::set_mouth_config(MouthConfig m){
88
    //lock access
89
    mutex::scoped_lock scoped_lock(mouth_config_override_mutex);
90

    
91
    mouth_config = m;
92
}
93

    
94
void Arbiter::set_gaze_target(humotion::GazeState target){
95
    //lock access
96
    mutex::scoped_lock scoped_lock(requested_gaze_state_mutex);
97

    
98
    requested_gaze_state = target;
99
}
100

    
101
void Arbiter::set_mouth_target(humotion::MouthState target){
102
    //lock access
103
    mutex::scoped_lock scoped_lock(requested_mouth_state_mutex);
104

    
105
    requested_mouth_state = target;
106
}
107

    
108
//! note: this is blocking!
109
void Arbiter::play_animation(boost::shared_ptr<Animation> incoming_animation){
110
    //incoming animation, check if this would conflict with any pending animations:
111
    //lock access & iterate over vector:
112
    mutex::scoped_lock lock_av(active_animation_vector_mutex);
113
    active_animation_vector_t::iterator it;
114
    for(it = active_animation_vector.begin(); it<active_animation_vector.end(); it++){
115
        boost::shared_ptr<Animation> current_ani = *it;
116
        //check if the running animation collides with the incoming animation:
117
        if (current_ani->collides_with(incoming_animation.get())){
118
            //this would fail, we can not play this animation right now!
119
            throw runtime_error("incoming animation collides with unfinished active animation");
120
            return;
121
        }
122
    }
123

    
124
    //ok, fine. no other animations are active that would collide with the new request
125
    //thus it is safe to enqueue this item:
126
    active_animation_vector.push_back(incoming_animation);
127

    
128
    //unlock mutex
129
    lock_av.unlock();
130

    
131
    //start playback!
132
    incoming_animation->start();
133

    
134
    //block until ani was played back
135
    while(incoming_animation->is_active()){
136
        //printf("A"); fflush(stdout);
137
        usleep(1*1000); //1ms, save cpu cycles
138
    }
139

    
140
    //ok, it finished. we can safely remove it now:
141
    lock_av.lock();
142
    for(it = active_animation_vector.begin(); it<active_animation_vector.end();){
143
        boost::shared_ptr<Animation> current_ani = *it;
144
        if (*it == incoming_animation){
145
            //printf(">match -> remove incoming ani again\n");
146
            it = active_animation_vector.erase(it);
147
          }else{
148
            ++it;
149
          }
150
    }
151
}
152

    
153
void Arbiter::speak(boost::shared_ptr<Utterance> u){ //, ao_sample_format audio_format, char *audio_data, unsigned int audio_len){
154
    //lock audio playback as such:
155
    mutex::scoped_lock scoped_lock_audio(audio_player_mutex);
156

    
157
    //lock utterance & store data:
158
    mutex::scoped_lock scoped_lock(utterance_mutex);
159
    utterance = u;
160
    scoped_lock.unlock();
161

    
162
    //start audio playback, this function returns once we started playback
163
    if (audio_player == NULL){
164
        printf("> audio_player disabled, not speaking '%s'\n", u.get()->get_text().c_str());
165
    }else{
166
        audio_player->play(utterance->get_audio_data());
167
    }
168
    utterance->start_playback();
169

    
170
    //wait until audio playback was finished:
171
    if (audio_player != NULL){
172
        while(audio_player->is_playing()){
173
            //save some cpu cycles:
174
            usleep(1*1000); //1ms
175
        }
176
    }
177

    
178
    //in case the audio output fails, we end up here before the utterance is finished.
179
    //so check now if the utterance finished as well:
180
    while (utterance->is_playing()){
181
        //save some cpu cycles:
182
        usleep(1*1000); //1ms
183
    }
184

    
185
}
186

    
187
bool Arbiter::speak_active(){
188
    if (audio_player == NULL){
189
        return false;
190
    }else{
191
        return audio_player->is_playing();
192
    }
193
}
194

    
195
void Arbiter::arbitrate(){
196
    //handle arbitration, DO NOT RE-ORDER these calls!
197

    
198
    //try to process all incoming requests
199
    override_by_emotion();
200

    
201
    //overwrite with mouth targets from outside:
202
    override_by_mouth();
203

    
204
    //lip animation
205
    override_by_utterance();
206

    
207
    //animations
208
    override_by_animation();
209

    
210
    //gaze target is set by requested_gaze_target
211
    override_by_gaze();
212
}
213

    
214
void Arbiter::override_by_utterance(){
215
    //fetch MouthState by utterance:
216
    if (!utterance->is_playing()){
217
        //not playing -> return
218
        return;
219
    }
220

    
221
    //fetch symbol
222
    string symbol = utterance->currently_active_phoneme();
223
    if ((symbol.empty()) || (symbol == "")){
224
        return;
225
    }
226

    
227
    //fetch config
228
    mouth_config.init_by_symbol(symbol);
229

    
230
    //overwrite mouth with offsets from utterance player
231
    mouth_config.apply_on_mouth_state(&mouth_state);
232
}
233

    
234
void Arbiter::override_by_mouth(){
235
    //external mouth requests can overwrite the mouth targets!
236
    if ((requested_mouth_state.position_center + requested_mouth_state.position_left + requested_mouth_state.position_right) > 0.0){
237
        //values given -> override emotion data
238
        mouth_state = requested_mouth_state;
239
    }
240
    //requested_mouth_state.dump();
241
    //mouth_state.dump();
242
}
243

    
244
void Arbiter::override_by_gaze(){
245
    //copy from requested target:
246
    gaze_state.pan   = requested_gaze_state.pan;
247
    gaze_state.tilt  = requested_gaze_state.tilt;
248
    gaze_state.roll  = requested_gaze_state.roll;
249

    
250
    gaze_state.gaze_type = requested_gaze_state.gaze_type;
251
    gaze_state.timestamp = requested_gaze_state.timestamp;
252
    gaze_state.vergence  = requested_gaze_state.vergence;
253

    
254
    //add offset values from user:
255
    gaze_state.pan_offset  += requested_gaze_state.pan_offset;
256
    gaze_state.tilt_offset += requested_gaze_state.tilt_offset;
257

    
258
}
259

    
260
void Arbiter::override_by_emotion(){
261
    //lock access
262
    mutex::scoped_lock scoped_lock1(emotion_config_default_mutex);
263
    mutex::scoped_lock scoped_lock2(emotion_config_current_mutex);
264

    
265
    EmotionConfig *emotion_target = &emotion_config_default;
266

    
267
    //which emotion is active?
268
    if (emotion_config_current.is_active()){
269
        //current emotion is not timed out, override default
270
        emotion_target = &emotion_config_current;
271
    }
272

    
273
    //emotions will set the mouth state here (will be overwritten by speak)
274
    mouth_state = emotion_target->mouth_override;
275

    
276
    //emotions will add an offset to the gaze state:
277
    //pan,tilt,roll will be overwritten by override_by_gaze() we only keep the offset values from this!
278
    //FIXME: change to eyelid opening  upper/lower once humotion supports it
279
    //eyebrow angles come from this
280
    gaze_state = emotion_target->gaze_override;
281
    //gaze_state.dump();
282

    
283
    //IMPORTANT: clear request from emotion target:
284
    emotion_target->gaze_override.eyeblink_request_left = 0;
285
    emotion_target->gaze_override.eyeblink_request_right = 0;
286

    
287
}
288

    
289

    
290
void Arbiter::override_by_animation(){
291
    //lock access & iterate over vector:
292
    mutex::scoped_lock lock_av(active_animation_vector_mutex);
293
    active_animation_vector_t::iterator it;
294
    for(it = active_animation_vector.begin(); it<active_animation_vector.end(); it++){
295
        boost::shared_ptr<Animation> current_ani = *it;
296

    
297
        //gaze_state.dump();
298
        current_ani->apply_on_gazestate(&gaze_state);
299
        //gaze_state.dump();
300
    }
301
}
302

    
303
humotion::GazeState Arbiter::get_gaze_state(){
304
    return gaze_state;
305
}
306

    
307
humotion::MouthState Arbiter::get_mouth_state(){
308
    return mouth_state;
309
}