1/*** 2 This file is part of PulseAudio. 3 4 Copyright 2009 Tanu Kaskinen 5 6 PulseAudio is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as published 8 by the Free Software Foundation; either version 2.1 of the License, 9 or (at your option) any later version. 10 11 PulseAudio is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public License 17 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 18***/ 19 20#ifdef HAVE_CONFIG_H 21#include <config.h> 22#endif 23 24#include <dbus/dbus.h> 25 26#include <pulsecore/core-scache.h> 27#include <pulsecore/core-util.h> 28#include <pulsecore/dbus-util.h> 29#include <pulsecore/protocol-dbus.h> 30 31#include "iface-memstats.h" 32 33#define OBJECT_NAME "memstats" 34 35static void handle_get_current_memblocks(DBusConnection *conn, DBusMessage *msg, void *userdata); 36static void handle_get_current_memblocks_size(DBusConnection *conn, DBusMessage *msg, void *userdata); 37static void handle_get_accumulated_memblocks(DBusConnection *conn, DBusMessage *msg, void *userdata); 38static void handle_get_accumulated_memblocks_size(DBusConnection *conn, DBusMessage *msg, void *userdata); 39static void handle_get_sample_cache_size(DBusConnection *conn, DBusMessage *msg, void *userdata); 40 41static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); 42 43struct pa_dbusiface_memstats { 44 pa_core *core; 45 char *path; 46 pa_dbus_protocol *dbus_protocol; 47}; 48 49enum property_handler_index { 50 PROPERTY_HANDLER_CURRENT_MEMBLOCKS, 51 PROPERTY_HANDLER_CURRENT_MEMBLOCKS_SIZE, 52 PROPERTY_HANDLER_ACCUMULATED_MEMBLOCKS, 53 PROPERTY_HANDLER_ACCUMULATED_MEMBLOCKS_SIZE, 54 PROPERTY_HANDLER_SAMPLE_CACHE_SIZE, 55 PROPERTY_HANDLER_MAX 56}; 57 58static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { 59 [PROPERTY_HANDLER_CURRENT_MEMBLOCKS] = { .property_name = "CurrentMemblocks", .type = "u", .get_cb = handle_get_current_memblocks, .set_cb = NULL }, 60 [PROPERTY_HANDLER_CURRENT_MEMBLOCKS_SIZE] = { .property_name = "CurrentMemblocksSize", .type = "u", .get_cb = handle_get_current_memblocks_size, .set_cb = NULL }, 61 [PROPERTY_HANDLER_ACCUMULATED_MEMBLOCKS] = { .property_name = "AccumulatedMemblocks", .type = "u", .get_cb = handle_get_accumulated_memblocks, .set_cb = NULL }, 62 [PROPERTY_HANDLER_ACCUMULATED_MEMBLOCKS_SIZE] = { .property_name = "AccumulatedMemblocksSize", .type = "u", .get_cb = handle_get_accumulated_memblocks_size, .set_cb = NULL }, 63 [PROPERTY_HANDLER_SAMPLE_CACHE_SIZE] = { .property_name = "SampleCacheSize", .type = "u", .get_cb = handle_get_sample_cache_size, .set_cb = NULL } 64}; 65 66static pa_dbus_interface_info memstats_interface_info = { 67 .name = PA_DBUSIFACE_MEMSTATS_INTERFACE, 68 .method_handlers = NULL, 69 .n_method_handlers = 0, 70 .property_handlers = property_handlers, 71 .n_property_handlers = PROPERTY_HANDLER_MAX, 72 .get_all_properties_cb = handle_get_all, 73 .signals = NULL, 74 .n_signals = 0 75}; 76 77static void handle_get_current_memblocks(DBusConnection *conn, DBusMessage *msg, void *userdata) { 78 pa_dbusiface_memstats *m = userdata; 79 const pa_mempool_stat *stat; 80 dbus_uint32_t current_memblocks; 81 82 pa_assert(conn); 83 pa_assert(msg); 84 pa_assert(m); 85 86 stat = pa_mempool_get_stat(m->core->mempool); 87 88 current_memblocks = pa_atomic_load(&stat->n_allocated); 89 90 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, ¤t_memblocks); 91} 92 93static void handle_get_current_memblocks_size(DBusConnection *conn, DBusMessage *msg, void *userdata) { 94 pa_dbusiface_memstats *m = userdata; 95 const pa_mempool_stat *stat; 96 dbus_uint32_t current_memblocks_size; 97 98 pa_assert(conn); 99 pa_assert(msg); 100 pa_assert(m); 101 102 stat = pa_mempool_get_stat(m->core->mempool); 103 104 current_memblocks_size = pa_atomic_load(&stat->allocated_size); 105 106 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, ¤t_memblocks_size); 107} 108 109static void handle_get_accumulated_memblocks(DBusConnection *conn, DBusMessage *msg, void *userdata) { 110 pa_dbusiface_memstats *m = userdata; 111 const pa_mempool_stat *stat; 112 dbus_uint32_t accumulated_memblocks; 113 114 pa_assert(conn); 115 pa_assert(msg); 116 pa_assert(m); 117 118 stat = pa_mempool_get_stat(m->core->mempool); 119 120 accumulated_memblocks = pa_atomic_load(&stat->n_accumulated); 121 122 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &accumulated_memblocks); 123} 124 125static void handle_get_accumulated_memblocks_size(DBusConnection *conn, DBusMessage *msg, void *userdata) { 126 pa_dbusiface_memstats *m = userdata; 127 const pa_mempool_stat *stat; 128 dbus_uint32_t accumulated_memblocks_size; 129 130 pa_assert(conn); 131 pa_assert(msg); 132 pa_assert(m); 133 134 stat = pa_mempool_get_stat(m->core->mempool); 135 136 accumulated_memblocks_size = pa_atomic_load(&stat->accumulated_size); 137 138 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &accumulated_memblocks_size); 139} 140 141static void handle_get_sample_cache_size(DBusConnection *conn, DBusMessage *msg, void *userdata) { 142 pa_dbusiface_memstats *m = userdata; 143 dbus_uint32_t sample_cache_size; 144 145 pa_assert(conn); 146 pa_assert(msg); 147 pa_assert(m); 148 149 sample_cache_size = pa_scache_total_size(m->core); 150 151 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_cache_size); 152} 153 154static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { 155 pa_dbusiface_memstats *m = userdata; 156 const pa_mempool_stat *stat; 157 dbus_uint32_t current_memblocks; 158 dbus_uint32_t current_memblocks_size; 159 dbus_uint32_t accumulated_memblocks; 160 dbus_uint32_t accumulated_memblocks_size; 161 dbus_uint32_t sample_cache_size; 162 DBusMessage *reply = NULL; 163 DBusMessageIter msg_iter; 164 DBusMessageIter dict_iter; 165 166 pa_assert(conn); 167 pa_assert(msg); 168 pa_assert(m); 169 170 stat = pa_mempool_get_stat(m->core->mempool); 171 172 current_memblocks = pa_atomic_load(&stat->n_allocated); 173 current_memblocks_size = pa_atomic_load(&stat->allocated_size); 174 accumulated_memblocks = pa_atomic_load(&stat->n_accumulated); 175 accumulated_memblocks_size = pa_atomic_load(&stat->accumulated_size); 176 sample_cache_size = pa_scache_total_size(m->core); 177 178 pa_assert_se((reply = dbus_message_new_method_return(msg))); 179 180 dbus_message_iter_init_append(reply, &msg_iter); 181 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); 182 183 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CURRENT_MEMBLOCKS].property_name, DBUS_TYPE_UINT32, ¤t_memblocks); 184 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CURRENT_MEMBLOCKS_SIZE].property_name, DBUS_TYPE_UINT32, ¤t_memblocks_size); 185 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ACCUMULATED_MEMBLOCKS].property_name, DBUS_TYPE_UINT32, &accumulated_memblocks); 186 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_ACCUMULATED_MEMBLOCKS_SIZE].property_name, DBUS_TYPE_UINT32, &accumulated_memblocks_size); 187 pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_CACHE_SIZE].property_name, DBUS_TYPE_UINT32, &sample_cache_size); 188 189 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); 190 191 pa_assert_se(dbus_connection_send(conn, reply, NULL)); 192 193 dbus_message_unref(reply); 194} 195 196pa_dbusiface_memstats *pa_dbusiface_memstats_new(pa_dbusiface_core *dbus_core, pa_core *core) { 197 pa_dbusiface_memstats *m; 198 199 pa_assert(dbus_core); 200 pa_assert(core); 201 202 m = pa_xnew(pa_dbusiface_memstats, 1); 203 m->core = core; 204 m->path = pa_sprintf_malloc("%s/%s", PA_DBUS_CORE_OBJECT_PATH, OBJECT_NAME); 205 m->dbus_protocol = pa_dbus_protocol_get(core); 206 207 pa_assert_se(pa_dbus_protocol_add_interface(m->dbus_protocol, m->path, &memstats_interface_info, m) >= 0); 208 209 return m; 210} 211 212void pa_dbusiface_memstats_free(pa_dbusiface_memstats *m) { 213 pa_assert(m); 214 215 pa_assert_se(pa_dbus_protocol_remove_interface(m->dbus_protocol, m->path, memstats_interface_info.name) >= 0); 216 217 pa_xfree(m->path); 218 219 pa_dbus_protocol_unref(m->dbus_protocol); 220 221 pa_xfree(m); 222} 223 224const char *pa_dbusiface_memstats_get_path(pa_dbusiface_memstats *m) { 225 pa_assert(m); 226 227 return m->path; 228} 229