Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

# Licensed under the MIT license 

# http://opensource.org/licenses/mit-license.php 

 

# Copyright (C) 2006 Fluendo, S.A. (www.fluendo.com). 

# Copyright 2006, Frank Scholz <coherence@beebits.net> 

 

import time 

 

from coherence.upnp.core import utils 

 

try: 

    # FIXME:  there is some circular import, 

    # service imports variable, variable imports service 

    # how is this done properly? 

    from coherence.upnp.core import service 

except ImportError: 

    from . import service 

 

from coherence import log 

 

import coherence.extern.louie as louie 

 

 

class StateVariable(log.LogAble): 

    logCategory = 'variable' 

 

    def __init__(self, upnp_service, name, implementation, instance, 

                 send_events, 

                 data_type, allowed_values): 

        log.LogAble.__init__(self) 

        self.service = upnp_service 

 

        self.name = name 

        self.implementation = implementation 

        self.instance = instance 

        self.send_events = utils.means_true(send_events) 

        self.never_evented = False 

        self.data_type = data_type 

        self.allowed_values = allowed_values 

        if self.allowed_values is None: 

            self.allowed_values = [] 

        self.has_vendor_values = False 

        self.allowed_value_range = None 

        self.dependant_variable = None 

 

        self.default_value = '' 

        self.old_value = '' 

        self.value = '' 

        self.last_time_touched = None 

 

        self._callbacks = [] 

        if isinstance(self.service, service.ServiceServer): 

            self.moderated = self.service.is_variable_moderated(name) 

            self.updated = False 

 

    def as_tuples(self): 

        r = [] 

        r.append(('Name', self.name)) 

        if self.send_events: 

            r.append(('Evented', 'yes')) 

        else: 

            r.append(('Evented', 'no')) 

        r.append(('Data Type', self.data_type)) 

        r.append(('Default Value', self.default_value)) 

        r.append(('Current Value', str(self.value))) 

        if self.allowed_values is not None and \ 

                len(self.allowed_values) > 0: 

            r.append(('Allowed Values', 

                      ','.join(self.allowed_values))) 

        return r 

 

    def set_default_value(self, value): 

        self.update(value) 

        self.default_value = self.value 

 

    def set_allowed_values(self, values): 

        if not isinstance(values, (list, tuple)): 

            values = [values] 

        self.allowed_values = values 

 

    def set_allowed_value_range(self, **kwargs): 

        self.allowed_value_range = kwargs 

 

    def get_allowed_values(self): 

        return self.allowed_values 

 

    def set_never_evented(self, value): 

        self.never_evented = utils.means_true(value) 

 

    def update(self, value): 

        self.info("variable check for update %s %s %s", self.name, value, 

                  self.service) 

        if not isinstance(self.service, service.Service): 

            if self.name == 'ContainerUpdateIDs': 

                old_value = self.value 

                if self.updated: 

                    if isinstance(value, tuple): 

                        v = old_value.split(',') 

                        i = 0 

                        while i < len(v): 

                            if v[i] == str(value[0]): 

                                del v[i:i + 2] 

                                old_value = ','.join(v) 

                                break 

                            i += 2 

                        if len(old_value): 

                            new_value = old_value + ',' + str( 

                                value[0]) + ',' + str(value[1]) 

                        else: 

                            new_value = str(value[0]) + ',' + str(value[1]) 

                    else: 

                        if len(old_value): 

                            new_value = str(old_value) + ',' + str(value) 

                        else: 

                            new_value = str(value) 

                else: 

                    if isinstance(value, tuple): 

                        new_value = str(value[0]) + ',' + str(value[1]) 

                    else: 

                        new_value = value 

            else: 

                if self.data_type == 'string': 

                    if isinstance(value, str): 

                        value = value.split(',') 

                    if (isinstance(value, tuple) or 

                            isinstance(value, set)): 

                        value = list(value) 

                    if not isinstance(value, list): 

                        value = [value] 

                    new_value = [] 

                    for v in value: 

                        if type(v) == str: 

                            v = v  # .encode('utf-8') 

                        else: 

                            v = str(v) 

                        if len(self.allowed_values): 

                            if self.has_vendor_values: 

                                new_value.append(v) 

                            elif v.upper() in [x.upper() for x in 

                                               self.allowed_values]: 

                                new_value.append(v) 

                            else: 

                                self.warning( 

                                    "Variable %s update, %r value %s " 

                                    "doesn't fit in %r", 

                                    self.name, self.has_vendor_values, v, 

                                    self.allowed_values) 

                                new_value = 'Coherence_Value_Error' 

                        else: 

                            new_value.append(v) 

                    new_value = ','.join(new_value) 

                elif self.data_type == 'boolean': 

                    new_value = utils.generalise_boolean(value) 

                elif self.data_type == 'bin.base64': 

                    new_value = value 

                else: 

                    new_value = int(value) 

        else: 

            if self.data_type == 'string': 

                if type(value) != str: 

                    value = str(value) 

                if len(self.allowed_values): 

                    if self.has_vendor_values: 

                        new_value = value 

                    elif value.upper() in [v.upper() for v in 

                                           self.allowed_values]: 

                        new_value = value 

                    else: 

                        self.warning( 

                            "Variable %s NOT updated, value %s doesn't fit", 

                            self.name, value) 

                        new_value = 'Coherence_Value_Error' 

                else: 

                    new_value = value 

            elif self.data_type == 'boolean': 

                new_value = utils.generalise_boolean(value) 

            elif self.data_type == 'bin.base64': 

                new_value = value 

            else: 

                try: 

                    new_value = int(value) 

                except ValueError: 

                    new_value = 'Coherence_Value_Error' 

 

        if new_value == 'Coherence_Value_Error': 

            return 

        if new_value == self.value: 

            self.info("variable NOT updated, no value change %s %s", self.name, 

                      self.value) 

            return 

        self.old_value = self.value 

        self.value = new_value 

        self.last_time_touched = time.time() 

 

        # print("UPDATED %s %r %r %r %r %r" % ( 

        #     self.name, self.service, 

        #     isinstance(self.service, service.Service), 

        #     self.instance, self.value, self._callbacks)) 

        self.notify() 

 

        if isinstance(self.service, service.Service): 

            # self.notify() 

            pass 

        else: 

            self.updated = True 

            if self.service.last_change is not None: 

                self.service.last_change.updated = True 

        self.info("variable updated %s %s", self.name, self.value) 

 

    def subscribe(self, callback): 

        self._callbacks.append(callback) 

        callback(self) 

 

    def notify(self): 

        if self.name.startswith('A_ARG_TYPE_'): 

            return 

        self.info("Variable %s sends notify about new value >%r<", self.name, 

                  self.value) 

        # if self.old_value == '': 

        #    return 

        louie.send( 

            signal='Coherence.UPnP.StateVariable.%s.changed' % self.name, 

            sender=self.service, variable=self) 

        louie.send( 

            signal='Coherence.UPnP.StateVariable.changed', 

            sender=self.service, variable=self) 

        # print("CALLBACKS %s %r %r" % ( 

        #     self.name, self.instance, self._callbacks)) 

        for callback in self._callbacks: 

            callback(self) 

 

    def __repr__(self): 

        return "Variable: %s, %s, %d, %s, %s, %s, %s, %s, %s, %s" % \ 

               (self.name, 

                str(self.service), 

                self.instance, 

                self.implementation, 

                self.data_type, 

                str(self.allowed_values), 

                str(self.default_value), 

                str(self.old_value), 

                str(self.value), 

                str(self.send_events))