initial upload
[apps/native/smart-surveillance-camera.git] / src / switch.c
1  /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18 #include <pthread.h>
19 #include <glib.h>
20 #include "log.h"
21 #include "switch.h"
22
23 #define IDLE_PRIORITY (G_PRIORITY_HIGH_IDLE + 30)
24
25 struct switch_data_s {
26         switch_state_e state;
27         GHashTable *callback_hash;
28 };
29
30 struct switch_callback_s {
31         switch_state_changed_cb callback;
32         void *cb_data;
33 };
34
35 struct switch_pass_data_s {
36         char *pass_key;
37         switch_state_e state;
38 };
39
40 static struct switch_data_s *g_switch;
41 static pthread_mutex_t g_switch_mutex;
42
43 static int __free_switch_handle(struct switch_data_s *sw)
44 {
45         if (sw->callback_hash) {
46                 g_hash_table_destroy(sw->callback_hash);
47                 g_hash_table_unref(sw->callback_hash);
48         }
49
50         free(sw);
51         return 0;
52 }
53
54 int switch_initialize(void)
55 {
56         if (g_switch) {
57                 _D("The switch is already initialized!");
58                 return 0;
59         }
60
61         g_switch = malloc(sizeof(struct switch_data_s));
62         retv_if(!g_switch, -1);
63
64         g_switch->callback_hash =
65                 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
66
67         pthread_mutex_init(&g_switch_mutex, NULL);
68         g_switch->state = SWITCH_STATE_OFF;
69
70         /* TODO : initialize real switch here */
71
72         return 0;
73 }
74
75 int switch_finalize(void)
76 {
77         if (g_switch) {
78                 pthread_mutex_destroy(&g_switch_mutex);
79                 __free_switch_handle(g_switch);
80                 g_switch = NULL;
81         }
82
83         return 0;
84 }
85
86 static void __cb_item_foreach(gpointer key, gpointer value, gpointer user_data)
87 {
88         char *item_name = key;
89         struct switch_callback_s *cb_item = value;
90         struct switch_pass_data_s *pass_item = user_data;
91
92         ret_if(!item_name);
93         ret_if(!cb_item);
94         ret_if(!pass_item);
95
96
97         if (pass_item->pass_key &&
98                 (0 == g_strcmp0(item_name, pass_item->pass_key))) {
99                         // _D("pass item - %s", item_name);
100                         return;
101                 }
102
103         _D("callback called for [%s]", item_name);
104         cb_item->callback(pass_item->state, cb_item->cb_data);
105 }
106
107 static gboolean __call_cb_idle(gpointer data)
108 {
109         struct switch_pass_data_s *pass_item = data;
110
111         g_hash_table_foreach(g_switch->callback_hash, __cb_item_foreach, pass_item);
112         g_free(pass_item->pass_key);
113         g_free(pass_item);
114
115         return G_SOURCE_REMOVE;
116 }
117
118 int switch_state_set(switch_state_e state, const char *pass_key)
119 {
120         int old_state = 0;
121         retv_if(!g_switch, -1);
122
123         pthread_mutex_lock(&g_switch_mutex);
124         old_state = g_switch->state;
125         pthread_mutex_unlock(&g_switch_mutex);
126
127         if (old_state != state) {
128                 pthread_mutex_lock(&g_switch_mutex);
129                 g_switch->state = state;
130                 pthread_mutex_unlock(&g_switch_mutex);
131
132                 if (g_hash_table_size(g_switch->callback_hash) > 0) {
133                         struct switch_pass_data_s *pass_item = NULL;
134
135                         pass_item = g_new(struct switch_pass_data_s, 1);
136                         pass_item->pass_key = g_strdup(pass_key);
137                         pass_item->state = state;
138                         g_idle_add_full(IDLE_PRIORITY,
139                                 __call_cb_idle, pass_item, NULL);
140                 }
141         }
142         return 0;
143 }
144
145 int switch_state_get(switch_state_e *state)
146 {
147         retv_if(!g_switch, -1);
148         retv_if(!state, -1);
149
150         pthread_mutex_lock(&g_switch_mutex);
151         *state = g_switch->state;
152         pthread_mutex_unlock(&g_switch_mutex);
153
154         // _D("get state : %d", *state);
155
156         return 0;
157 }
158
159 int switch_state_changed_cb_set(
160         const char *callback_key, switch_state_changed_cb callback, void *cb_data)
161 {
162         retv_if(!g_switch, -1);
163         retv_if(!g_switch->callback_hash, -1);
164         retv_if(!callback_key, -1);
165
166         if (callback) {
167                 struct switch_callback_s *cb_item = NULL;
168                 cb_item = g_try_new(struct switch_callback_s, 1);
169                 retv_if(!cb_item, -1);
170
171                 cb_item->callback = callback;
172                 cb_item->cb_data = cb_data;
173
174                 g_hash_table_insert(g_switch->callback_hash,
175                         g_strdup(callback_key), cb_item);
176         } else {
177                 g_hash_table_remove(g_switch->callback_hash, callback_key);
178         }
179
180         return 0;
181 }