~ubuntu-branches/ubuntu/karmic/ekiga/karmic

« back to all changes in this revision

Viewing changes to lib/engine/presence/local-roster/local-heap.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ken VanDine
  • Date: 2009-03-17 15:14:12 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090317151412-no6uq0wl8zz2hsw3
Tags: 3.2.0-0ubuntu1
* New upstream release (LP: #341367)
  - Better NAT support in case of Cone NAT
  - Uniformise detection of libnotify; fix compilation with mingw
  - Fix "URL completion combobox shows identical completions"
  - Fix "Assistant loosing values when going backward"
  - Fix GmConf settings when compiled with another package name
  - Fix unregistration of accounts
  - Fix build with --enable-kde
  - Fixed possible crash when retrieving presence information
  - New translations: crh, or
  - Updated translations: as, bg, bn_IN, da, de, el, eu, gl, gu, hi, hu,
    ja, kn, ko, ku, lt, ml, mr, or, pt, ro, ru, ta, te, tr
  - New help translation: en_GB
  - Updated help translation: fr
  - Better NAT support in case of Cone NAT
  - There is now only one H.263 plugin implementing both H.263 and H.263+
  - Allow several ALSA devices to have the same name
  - Added support for the G.722 audio codec: G.722 is a 16 kHz wideband
    audio codec advertised as HD Voice by the famous Polycom. It is a
    great boost in quality and interoperability
  - Added support for the CELT ultral-low delay audio codec: CELT delivers
    high quality audio at 32 kHz or 48 kHz, allowing to transmit music in
    high quality, with low delay and low bitrate
  - Added support for SIP dialog-info notifications: they allow displaying
    notifications of incoming calls in the roster. With software like
    kamailio or Asterisk, it allows being informed of incoming calls
    reaching your colleagues
  - Largely improved LDAP support: the OpenLDAP guys contributed several
    patches to provide state-of-the-art LDAP support in the Ekiga address
    book. The new code even supports authentication
  - Killed the gconf_test_age test, Ekiga can now finally work with
    badly installed GConf schemas
  - Better handling of multiple network interfaces with dynamic addition
    and removal
  - Added settings migration from Ekiga 2.0.x.
  - Other various fixes, cleanups, removal of deprecated symbols etc.
  - New translations: crh, or
  - New help translation: en_GB, eu
  - Updated many translations and help
  - Experimental features:
    * Significant improvements in IPv6 support
    * Gstreamer audio and video capture support near to be finished...
* debian/patches/migrate_2.0_settings.patch:
  - Removed, migration is now upstream
* debian/patches/00_news.patch
  - Removed
* debian/patches/ubuntu_lpi.patch:
  - Modified to work with 3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
/*
3
 
 * Ekiga -- A VoIP and Video-Conferencing application
4
 
 * Copyright (C) 2000-2007 Damien Sandras
5
 
 
6
 
 * This program is free software; you can  redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or (at
9
 
 * your option) any later version. This program is distributed in the hope
10
 
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
11
 
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
 
 * See the GNU General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU General Public License along
15
 
 * with this program; if not, write to the Free Software Foundation, Inc.,
16
 
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17
 
 *
18
 
 * Ekiga is licensed under the GPL license and as a special exception, you
19
 
 * have permission to link or otherwise combine this program with the
20
 
 * programs OPAL, OpenH323 and PWLIB, and distribute the combination, without
21
 
 * applying the requirements of the GNU GPL to the OPAL, OpenH323 and PWLIB
22
 
 * programs, as long as you do follow the requirements of the GNU GPL for all
23
 
 * the rest of the software thus combined.
24
 
 */
25
 
 
26
 
 
27
 
/*
28
 
 *                         local-heap.cpp  -  description
29
 
 *                         ------------------------------------------
30
 
 *   begin                : written in 2007 by Julien Puydt
31
 
 *   copyright            : (c) 2007 by Julien Puydt
32
 
 *   description          : implementation of the heap of the local roster
33
 
 *
34
 
 */
35
 
 
36
 
#include <iostream>
37
 
#include <set>
38
 
 
39
 
#include "config.h"
40
 
 
41
 
#include "gmconf.h"
42
 
#include "form-request-simple.h"
43
 
 
44
 
#include "local-heap.h"
45
 
 
46
 
#define KEY "/apps/" PACKAGE_NAME "/contacts/roster"
47
 
 
48
 
 
49
 
/*
50
 
 * Public API
51
 
 */
52
 
Local::Heap::Heap (Ekiga::ServiceCore &_core): core (_core), doc (NULL)
53
 
{
54
 
  xmlNodePtr root;
55
 
 
56
 
  presence_core = dynamic_cast<Ekiga::PresenceCore*>(core.get ("presence-core"));
57
 
 
58
 
  gchar *c_raw = gm_conf_get_string (KEY);
59
 
 
60
 
  // Build the XML document representing the contacts list from the configuration
61
 
  if (c_raw != NULL) {
62
 
 
63
 
    const std::string raw = c_raw;
64
 
    doc = xmlRecoverMemory (raw.c_str (), raw.length ());
65
 
 
66
 
    root = xmlDocGetRootElement (doc);
67
 
    if (root == NULL) {
68
 
 
69
 
      root = xmlNewDocNode (doc, NULL, BAD_CAST "list", NULL);
70
 
      xmlDocSetRootElement (doc, root);
71
 
    }
72
 
 
73
 
    for (xmlNodePtr child = root->children; child != NULL; child = child->next)
74
 
      if (child->type == XML_ELEMENT_NODE
75
 
          && child->name != NULL
76
 
          && xmlStrEqual (BAD_CAST ("entry"), child->name))
77
 
        add (child);
78
 
 
79
 
    g_free (c_raw);
80
 
 
81
 
    // Or create a new XML document
82
 
  }
83
 
  else {
84
 
 
85
 
    doc = xmlNewDoc (BAD_CAST "1.0");
86
 
    root = xmlNewDocNode (doc, NULL, BAD_CAST "list", NULL);
87
 
    xmlDocSetRootElement (doc, root);
88
 
 
89
 
    {
90
 
      // add 500 and 501 at ekiga.net in this case!
91
 
      std::set<std::string> groups;
92
 
 
93
 
      groups.insert (_("Services"));
94
 
      add (_("Echo test"), "sip:500@ekiga.net", groups);
95
 
      add (_("Conference room"), "sip:501@ekiga.net", groups);
96
 
    }
97
 
  }
98
 
}
99
 
 
100
 
 
101
 
Local::Heap::~Heap ()
102
 
{
103
 
  if (doc != NULL)
104
 
    xmlFreeDoc (doc);
105
 
}
106
 
 
107
 
 
108
 
const std::string
109
 
Local::Heap::get_name () const
110
 
{
111
 
  return _("Local roster");
112
 
}
113
 
 
114
 
 
115
 
bool
116
 
Local::Heap::populate_menu (Ekiga::MenuBuilder &builder)
117
 
{
118
 
  builder.add_action ("new", _("New contact"),
119
 
                      sigc::bind (sigc::mem_fun (this, &Local::Heap::new_presentity), "", ""));
120
 
  return true;
121
 
}
122
 
 
123
 
 
124
 
bool
125
 
Local::Heap::populate_menu_for_group (const std::string name,
126
 
                                      Ekiga::MenuBuilder& builder)
127
 
{
128
 
  builder.add_action ("rename_group", _("Rename"),
129
 
                      sigc::bind (sigc::mem_fun (this, &Local::Heap::on_rename_group), name));
130
 
  return true;
131
 
}
132
 
 
133
 
 
134
 
bool
135
 
Local::Heap::has_presentity_with_uri (const std::string uri) const
136
 
{
137
 
  bool result = false;
138
 
 
139
 
  for (const_iterator iter = begin ();
140
 
       iter != end () && result != true;
141
 
       iter++)
142
 
    result = (iter->get_uri () == uri);
143
 
 
144
 
  return result;
145
 
}
146
 
 
147
 
 
148
 
const std::set<std::string>
149
 
Local::Heap::existing_groups () const
150
 
{
151
 
  std::set<std::string> result;
152
 
 
153
 
  for (const_iterator iter = begin ();
154
 
       iter != end ();
155
 
       iter++) {
156
 
 
157
 
    std::set<std::string> groups = iter->get_groups ();
158
 
    result.insert (groups.begin (), groups.end ());
159
 
  }
160
 
 
161
 
  return result;
162
 
}
163
 
 
164
 
 
165
 
void
166
 
Local::Heap::new_presentity (const std::string name,
167
 
                             const std::string uri)
168
 
{
169
 
  if (!has_presentity_with_uri (uri)) {
170
 
 
171
 
    Ekiga::FormRequestSimple request;
172
 
    std::set<std::string> groups = existing_groups ();
173
 
 
174
 
    request.title (_("Add to local roster"));
175
 
    request.instructions (_("Please fill in this form to add a new contact "
176
 
                            "to ekiga's internal roster"));
177
 
    request.text ("name", _("Name:"), name);
178
 
    if (presence_core->is_supported_uri (uri)) {
179
 
 
180
 
      request.hidden ("good-uri", "yes");
181
 
      request.hidden ("uri", uri);
182
 
    } else {
183
 
 
184
 
      request.hidden ("good-uri", "no");
185
 
      if ( !uri.empty ())
186
 
        request.text ("uri", _("Address:"), uri);
187
 
      else
188
 
        request.text ("uri", _("Address:"), "sip:"); // let's put a default
189
 
    }
190
 
 
191
 
    request.editable_set ("groups",
192
 
                          _("Put contact in groups:"),
193
 
                          std::set<std::string>(), groups);
194
 
 
195
 
    request.submitted.connect (sigc::mem_fun (this, &Local::Heap::new_presentity_form_submitted));
196
 
 
197
 
    if (!questions.handle_request (&request)) {
198
 
 
199
 
    // FIXME: better error reporting
200
 
#ifdef __GNUC__
201
 
      std::cout << "Unhandled form request in "
202
 
                << __PRETTY_FUNCTION__ << std::endl;
203
 
#endif
204
 
    }
205
 
  }
206
 
}
207
 
 
208
 
 
209
 
/*
210
 
 * Private API
211
 
 */
212
 
void
213
 
Local::Heap::add (xmlNodePtr node)
214
 
{
215
 
  Presentity *presentity = NULL;
216
 
 
217
 
  presentity = new Presentity (core, node);
218
 
 
219
 
  common_add (*presentity);
220
 
}
221
 
 
222
 
 
223
 
void
224
 
Local::Heap::add (const std::string name,
225
 
                  const std::string uri,
226
 
                  const std::set<std::string> groups)
227
 
{
228
 
  Presentity *presentity = NULL;
229
 
  xmlNodePtr root = NULL;
230
 
 
231
 
  root = xmlDocGetRootElement (doc);
232
 
  presentity = new Presentity (core, name, uri, groups);
233
 
 
234
 
  xmlAddChild (root, presentity->get_node ());
235
 
 
236
 
  save ();
237
 
  common_add (*presentity);
238
 
}
239
 
 
240
 
 
241
 
void
242
 
Local::Heap::common_add (Presentity &presentity)
243
 
{
244
 
  // Add the presentity to this Heap
245
 
  add_presentity (presentity);
246
 
 
247
 
  // Fetch presence
248
 
  presence_core->fetch_presence (presentity.get_uri ());
249
 
 
250
 
  // Connect the Local::Presentity signals.
251
 
  presentity.trigger_saving.connect (sigc::mem_fun (this, &Local::Heap::save));
252
 
}
253
 
 
254
 
 
255
 
void
256
 
Local::Heap::save () const
257
 
{
258
 
  xmlChar *buffer = NULL;
259
 
  int size = 0;
260
 
 
261
 
  xmlDocDumpMemory (doc, &buffer, &size);
262
 
 
263
 
  gm_conf_set_string (KEY, (const char *)buffer);
264
 
 
265
 
  xmlFree (buffer);
266
 
}
267
 
 
268
 
 
269
 
void
270
 
Local::Heap::new_presentity_form_submitted (Ekiga::Form &result)
271
 
{
272
 
  try {
273
 
 
274
 
    const std::string name = result.text ("name");
275
 
    const std::string good_uri = result.hidden ("good-uri");
276
 
    std::string uri;
277
 
    const std::set<std::string> groups = result.editable_set ("groups");
278
 
 
279
 
    if (good_uri == "yes")
280
 
      uri = result.hidden ("uri");
281
 
    else
282
 
      uri = result.text ("uri");
283
 
 
284
 
    if (presence_core->is_supported_uri (uri)
285
 
        && !has_presentity_with_uri (uri)) {
286
 
 
287
 
      add (name, uri, groups);
288
 
      save ();
289
 
    } else {
290
 
 
291
 
      Ekiga::FormRequestSimple request;
292
 
 
293
 
      result.visit (request);
294
 
      if (!presence_core->is_supported_uri (uri))
295
 
        request.error (_("You supplied an unsupported address"));
296
 
      else
297
 
        request.error (_("You already have a contact with this address!"));
298
 
      request.submitted.connect (sigc::mem_fun (this, &Local::Heap::new_presentity_form_submitted));
299
 
      if (!questions.handle_request (&request)) {
300
 
 
301
 
        // FIXME: better error handling
302
 
#ifdef __GNUC__
303
 
        std::cout << "Unhandled form request in "
304
 
                  << __PRETTY_FUNCTION__ << std::endl;
305
 
#endif
306
 
      }
307
 
    }
308
 
  } catch (Ekiga::Form::not_found) {
309
 
 
310
 
#ifdef __GNUC__
311
 
    std::cerr << "Invalid form submitted to "
312
 
              << __PRETTY_FUNCTION__ << std::endl;
313
 
#endif
314
 
  }
315
 
}
316
 
 
317
 
void
318
 
Local::Heap::on_rename_group (std::string name)
319
 
{
320
 
  Ekiga::FormRequestSimple request;
321
 
 
322
 
  request.title (_("Rename group"));
323
 
  request.instructions (_("Please edit this group name"));
324
 
  request.text ("name", _("Name:"), name);
325
 
 
326
 
  request.submitted.connect (sigc::bind<0>(sigc::mem_fun (this, &Local::Heap::rename_group_form_submitted), name));
327
 
 
328
 
  if (!questions.handle_request (&request)) {
329
 
 
330
 
    // FIXME: better error reporting
331
 
#ifdef __GNUC__
332
 
    std::cout << "Unhandled form request in "
333
 
              << __PRETTY_FUNCTION__ << std::endl;
334
 
#endif
335
 
  }
336
 
}
337
 
 
338
 
void
339
 
Local::Heap::rename_group_form_submitted (std::string old_name,
340
 
                                          Ekiga::Form& result)
341
 
{
342
 
  try {
343
 
    const std::string new_name = result.text ("name");
344
 
 
345
 
    if ( !new_name.empty () && new_name != old_name) {
346
 
 
347
 
      for (iterator iter = begin ();
348
 
           iter != end ();
349
 
           ++iter) {
350
 
 
351
 
        iter->rename_group (old_name, new_name);
352
 
      }
353
 
    }
354
 
  } catch (Ekiga::Form::not_found) {
355
 
 
356
 
#ifdef __GNUC__
357
 
    std::cerr << "Invalid form submitted to "
358
 
              << __PRETTY_FUNCTION__ << std::endl;
359
 
#endif
360
 
  }
361
 
}