1/*
2 * libjingle
3 * Copyright 2004--2005, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef _STATUS_H_
29#define _STATUS_H_
30
31#include "talk/xmpp/jid.h"
32#include "talk/xmpp/constants.h"
33
34#define GOOGLE_CLIENT_NODE "http://www.google.com/xmpp/client/caps"
35
36namespace buzz {
37
38class Status {
39public:
40  Status() :
41    pri_(0),
42    show_(SHOW_NONE),
43    available_(false),
44    e_code_(0),
45    feedback_probation_(false),
46    know_capabilities_(false),
47    phone_capability_(false),
48    pmuc_capability_(false),
49    video_capability_(false),
50    camera_capability_(false),
51    is_google_client_(false) {}
52
53  ~Status() {}
54
55  // These are arranged in "priority order", i.e., if we see
56  // two statuses at the same priority but with different Shows,
57  // we will show the one with the highest show in the following
58  // order.
59  enum Show {
60    SHOW_NONE     = 0,
61    SHOW_OFFLINE  = 1,
62    SHOW_XA       = 2,
63    SHOW_AWAY     = 3,
64    SHOW_DND      = 4,
65    SHOW_ONLINE   = 5,
66    SHOW_CHAT     = 6,
67  };
68
69  const Jid & jid() const { return jid_; }
70  int priority() const { return pri_; }
71  Show show() const { return show_; }
72  const std::string & status() const { return status_; }
73  bool available() const { return available_ ; }
74  int error_code() const { return e_code_; }
75  const std::string & error_string() const { return e_str_; }
76  bool know_capabilities() const { return know_capabilities_; }
77  bool phone_capability() const { return phone_capability_; }
78  bool pmuc_capability() const { return pmuc_capability_; }
79  bool video_capability() const { return video_capability_; }
80  bool camera_capability() const { return camera_capability_; }
81  bool is_google_client() const { return is_google_client_; }
82  const std::string & version() const { return version_; }
83  bool feedback_probation() const { return feedback_probation_; }
84  const std::string& sent_time() const { return sent_time_; }
85
86  void set_jid(const Jid & jid) { jid_ = jid; }
87  void set_priority(int pri) { pri_ = pri; }
88  void set_show(Show show) { show_ = show; }
89  void set_status(const std::string & status) { status_ = status; }
90  void set_available(bool a) { available_ = a; }
91  void set_error(int e_code, const std::string e_str)
92      { e_code_ = e_code; e_str_ = e_str; }
93  void set_know_capabilities(bool f) { know_capabilities_ = f; }
94  void set_phone_capability(bool f) { phone_capability_ = f; }
95  void set_pmuc_capability(bool f) { pmuc_capability_ = f; }
96  void set_video_capability(bool f) { video_capability_ = f; }
97  void set_camera_capability(bool f) { camera_capability_ = f; }
98  void set_is_google_client(bool f) { is_google_client_ = f; }
99  void set_version(const std::string & v) { version_ = v; }
100  void set_feedback_probation(bool f) { feedback_probation_ = f; }
101  void set_sent_time(const std::string& time) { sent_time_ = time; }
102
103  void UpdateWith(const Status & new_value) {
104    if (!new_value.know_capabilities()) {
105       bool k = know_capabilities();
106       bool i = is_google_client();
107       bool p = phone_capability();
108       std::string v = version();
109
110       *this = new_value;
111
112       set_know_capabilities(k);
113       set_is_google_client(i);
114       set_phone_capability(p);
115       set_version(v);
116    }
117    else {
118      *this = new_value;
119    }
120  }
121
122  bool HasQuietStatus() const {
123    if (status_.empty())
124      return false;
125    return !(QuietStatus().empty());
126  }
127
128  // Knowledge of other clients' silly automatic status strings -
129  // Don't show these.
130  std::string QuietStatus() const {
131    if (jid_.resource().find("Psi") != std::string::npos) {
132      if (status_ == "Online" ||
133          status_.find("Auto Status") != std::string::npos)
134        return STR_EMPTY;
135    }
136    if (jid_.resource().find("Gaim") != std::string::npos) {
137      if (status_ == "Sorry, I ran out for a bit!")
138        return STR_EMPTY;
139    }
140    return TrimStatus(status_);
141  }
142
143  std::string ExplicitStatus() const {
144    std::string result = QuietStatus();
145    if (result.empty()) {
146      result = ShowStatus();
147    }
148    return result;
149  }
150
151  std::string ShowStatus() const {
152    std::string result;
153    if (!available()) {
154      result = "Offline";
155    }
156    else {
157      switch (show()) {
158        case SHOW_AWAY:
159        case SHOW_XA:
160          result = "Idle";
161          break;
162        case SHOW_DND:
163          result = "Busy";
164          break;
165        case SHOW_CHAT:
166          result = "Chatty";
167          break;
168        default:
169          result = "Available";
170          break;
171      }
172    }
173    return result;
174  }
175
176  static std::string TrimStatus(const std::string & st) {
177    std::string s(st);
178    int j = 0;
179    bool collapsing = true;
180    for (unsigned int i = 0; i < s.length(); i+= 1) {
181      if (s[i] <= ' ' && s[i] >= 0) {
182        if (collapsing) {
183          continue;
184        }
185        else {
186          s[j] = ' ';
187          j += 1;
188          collapsing = true;
189        }
190      }
191      else {
192        s[j] = s[i];
193        j += 1;
194        collapsing = false;
195      }
196    }
197    if (collapsing && j > 0) {
198      j -= 1;
199    }
200    s.erase(j, s.length());
201    return s;
202  }
203
204private:
205  Jid jid_;
206  int pri_;
207  Show show_;
208  std::string status_;
209  bool available_;
210  int e_code_;
211  std::string e_str_;
212  bool feedback_probation_;
213
214  // capabilities (valid only if know_capabilities_
215  bool know_capabilities_;
216  bool phone_capability_;
217  bool pmuc_capability_;
218  bool video_capability_;
219  bool camera_capability_;
220  bool is_google_client_;
221  std::string version_;
222
223  std::string sent_time_; // from the jabber:x:delay element
224};
225
226class MucStatus : public Status {
227public:
228  MucStatus() : audio_src_id_(0), video_src_id_(0) {}
229  uint32 audio_src_id() const { return audio_src_id_; }
230  uint32 video_src_id() const { return video_src_id_; }
231  void set_audio_src_id(uint32 audio_src_id) {
232    audio_src_id_ = audio_src_id;
233  }
234  void set_video_src_id(uint32 video_src_id) {
235    video_src_id_ = video_src_id;
236  }
237private:
238  uint32 audio_src_id_;
239  uint32 video_src_id_;
240};
241
242}
243
244
245#endif
246