Statistics
| Branch: | Tag: | Revision:

hlrc / server / src / Arbiter.cpp @ 0c286af0

History | View | Annotate | Download (9.135 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.substr(0,3), "rsb")){
41
        #ifdef RSB_SUPPORT
42
            audio_player = new AudioPlayerRSB(audio_output);
43
        #else
44
            printf("> ERROR: hlc is compiled without RSB support, RSB audio transport not available, defaulting to libao (default output!)\n");
45
            audio_player = new AudioPlayerLibAO("");
46
        #endif
47
    }else{
48
        audio_player = new AudioPlayerLibAO(audio_output);
49
    }
50

    
51
    //set default emotion:
52
    emotion_config_current.init_sad();
53
    emotion_config_current.set_duration(2000);
54
    emotion_config_default.init_neutral();
55
}
56

    
57
Arbiter::~Arbiter(){
58
}
59

    
60
void Arbiter::set_default_emotion(EmotionState e){
61
    //lock access
62
    mutex::scoped_lock scoped_lock(emotion_config_default_mutex);
63

    
64
    //update our config, ignore duration as this is the default emotion
65
    emotion_config_default.select_config(e.value);
66

    
67
    printf("> stored default emotion\n");
68
}
69

    
70
void Arbiter::set_current_emotion(EmotionState e){
71
    //lock access
72
    mutex::scoped_lock scoped_lock(emotion_config_current_mutex);
73

    
74
    //this will set a emotion override for a given time, after the timeout
75
    //we will return to the default emotion state:
76
    emotion_config_current.select_config(e.value);
77
    emotion_config_current.set_duration(e.duration);
78

    
79
    printf("> stored current emotion (val=%d, duration = %dms)\n",e.value, e.duration);
80
}
81

    
82
void Arbiter::set_mouth_config(MouthConfig m){
83
    //lock access
84
    mutex::scoped_lock scoped_lock(mouth_config_override_mutex);
85

    
86
    mouth_config = m;
87
}
88

    
89
void Arbiter::set_gaze_target(humotion::GazeState target){
90
    //lock access
91
    mutex::scoped_lock scoped_lock(requested_gaze_state_mutex);
92

    
93
    requested_gaze_state = target;
94
}
95

    
96
void Arbiter::set_mouth_target(humotion::MouthState target){
97
    //lock access
98
    mutex::scoped_lock scoped_lock(requested_mouth_state_mutex);
99

    
100
    requested_mouth_state = target;
101
}
102

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

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

    
123
    //unlock mutex
124
    lock_av.unlock();
125

    
126
    //start playback!
127
    incoming_animation->start();
128

    
129
    //block until ani was played back
130
    while(incoming_animation->is_active()){
131
        //printf("A"); fflush(stdout);
132
        usleep(1*1000); //1ms, save cpu cycles
133
    }
134

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

    
148
void Arbiter::speak(Utterance u){ //, ao_sample_format audio_format, char *audio_data, unsigned int audio_len){
149
    //lock audio playback as such:
150
    mutex::scoped_lock scoped_lock_audio(audio_player_mutex);
151

    
152
    //lock utterance & store data:
153
    mutex::scoped_lock scoped_lock(utterance_mutex);
154
    utterance = u;
155
    scoped_lock.unlock();
156

    
157
    //start audio playback, this function returns once we started playback
158
    audio_player->play(utterance.get_audio_data());
159
    utterance.start_playback();
160

    
161
    //wait until audio playback was finished:
162
    while(audio_player->is_playing()){
163
        //save some cpu cycles:
164
        usleep(1*1000); //1ms
165
    }
166
    //in case the audio output fails, we end up here before the utterance is finished.
167
    //so check now if the utterance finished as well:
168
    while (utterance.is_playing()){
169
        //save some cpu cycles:
170
        usleep(1*1000); //1ms
171
    }
172

    
173
}
174

    
175
bool Arbiter::speak_active(){
176
    return audio_player->is_playing();
177
}
178

    
179
void Arbiter::arbitrate(){
180
    //handle arbitration, DO NOT RE-ORDER these calls!
181

    
182
    //try to process all incoming requests
183
    override_by_emotion();
184

    
185
    //overwrite with mouth targets from outside:
186
    override_by_mouth();
187

    
188
    //lip animation
189
    override_by_utterance();
190

    
191
    //animations
192
    override_by_animation();
193

    
194
    //gaze target is set by requested_gaze_target
195
    override_by_gaze();
196
}
197

    
198
void Arbiter::override_by_utterance(){
199
    //fetch MouthState by utterance:
200
    if (!utterance.is_playing()){
201
        //not playing -> return
202
        return;
203
    }
204

    
205
    //fetch symbol
206
    string symbol = utterance.currently_active_phoneme();
207
    if ((symbol.empty()) || (symbol == "")){
208
        return;
209
    }
210

    
211
    //fetch config
212
    mouth_config.init_by_symbol(symbol);
213

    
214
    //overwrite mouth with offsets from utterance player
215
    mouth_config.apply_on_mouth_state(&mouth_state);
216
}
217

    
218
void Arbiter::override_by_mouth(){
219
    //external mouth requests can overwrite the mouth targets!
220
    if ((requested_mouth_state.position_center + requested_mouth_state.position_left + requested_mouth_state.position_right) > 0.0){
221
        //values given -> override emotion data
222
        mouth_state = requested_mouth_state;
223
    }
224
    //requested_mouth_state.dump();
225
    //mouth_state.dump();
226
}
227

    
228
void Arbiter::override_by_gaze(){
229
    //copy from requested target:
230
    gaze_state.pan   = requested_gaze_state.pan;
231
    gaze_state.tilt  = requested_gaze_state.tilt;
232
    gaze_state.roll  = requested_gaze_state.roll;
233

    
234
    gaze_state.timestamp = requested_gaze_state.timestamp;
235
    gaze_state.vergence  = requested_gaze_state.vergence;
236

    
237
    //add offset values from user:
238
    gaze_state.pan_offset  += requested_gaze_state.pan_offset;
239
    gaze_state.tilt_offset += requested_gaze_state.tilt_offset;
240

    
241
}
242

    
243
void Arbiter::override_by_emotion(){
244
    //lock access
245
    mutex::scoped_lock scoped_lock1(emotion_config_default_mutex);
246
    mutex::scoped_lock scoped_lock2(emotion_config_current_mutex);
247

    
248
    EmotionConfig *emotion_target = &emotion_config_default;
249

    
250
    //which emotion is active?
251
    if (emotion_config_current.is_active()){
252
        //current emotion is not timed out, override default
253
        emotion_target = &emotion_config_current;
254
    }
255

    
256
    //emotions will set the mouth state here (will be overwritten by speak)
257
    mouth_state = emotion_target->mouth_override;
258

    
259
    //emotions will add an offset to the gaze state:
260
    //pan,tilt,roll will be overwritten by override_by_gaze() we only keep the offset values from this!
261
    //FIXME: change to eyelid opening  upper/lower once humotion supports it
262
    //eyebrow angles come from this
263
    gaze_state = emotion_target->gaze_override;
264
    //gaze_state.dump();
265

    
266
    //IMPORTANT: clear request from emotion target:
267
    emotion_target->gaze_override.eyeblink_request_left = 0;
268
    emotion_target->gaze_override.eyeblink_request_right = 0;
269

    
270
}
271

    
272

    
273
void Arbiter::override_by_animation(){
274
    //lock access & iterate over vector:
275
    mutex::scoped_lock lock_av(active_animation_vector_mutex);
276
    active_animation_vector_t::iterator it;
277
    for(it = active_animation_vector.begin(); it<active_animation_vector.end(); it++){
278
        boost::shared_ptr<Animation> current_ani = *it;
279

    
280
        //gaze_state.dump();
281
        current_ani->apply_on_gazestate(&gaze_state);
282
        //gaze_state.dump();
283
    }
284
}
285

    
286
humotion::GazeState Arbiter::get_gaze_state(){
287
    return gaze_state;
288
}
289

    
290
humotion::MouthState Arbiter::get_mouth_state(){
291
    return mouth_state;
292
}