Merge from trunk -r 23968:24181.
[blender-staging.git] / release / scripts / io / netrender / operators.py
1 import bpy
2 import sys, os
3 import http, http.client, http.server, urllib, socket
4 import webbrowser
5
6 from netrender.utils import *
7 import netrender.client as client
8 import netrender.model
9
10 @rnaOperator
11 class RENDER_OT_netclientanim(bpy.types.Operator):
12         '''Start rendering an animation on network'''
13         __idname__ = "render.netclientanim"
14         __label__ = "Animation on network"
15         
16         # List of operator properties, the attributes will be assigned
17         # to the class instance from the operator settings before calling.
18         
19         __props__ = []
20         
21         def poll(self, context):
22                 return True
23         
24         def execute(self, context):
25                 scene = context.scene
26                 
27                 conn = clientConnection(scene)
28                 
29                 if conn:
30                         # Sending file
31                         scene.network_render.job_id = client.clientSendJob(conn, scene, True)
32                         conn.close()
33                 
34                 bpy.ops.screen.render('INVOKE_AREA', animation=True)
35                 
36                 return ('FINISHED',)
37         
38         def invoke(self, context, event):
39                 return self.execute(context)
40
41 @rnaOperator
42 class RENDER_OT_netclientsend(bpy.types.Operator):
43         '''Send Render Job to the Network'''
44         __idname__ = "render.netclientsend"
45         __label__ = "Send job"
46         
47         # List of operator properties, the attributes will be assigned
48         # to the class instance from the operator settings before calling.
49         
50         __props__ = []
51         
52         def poll(self, context):
53                 return True
54         
55         def execute(self, context):
56                 scene = context.scene
57                 
58                 conn = clientConnection(scene)
59                 
60                 if conn:
61                         # Sending file
62                         scene.network_render.job_id = client.clientSendJob(conn, scene, True)
63                         conn.close()
64                 
65                 return ('FINISHED',)
66         
67         def invoke(self, context, event):
68                 return self.execute(context)
69
70 @rnaOperator
71 class RENDER_OT_netclientstatus(bpy.types.Operator):
72         '''Refresh the status of the current jobs'''
73         __idname__ = "render.netclientstatus"
74         __label__ = "Client Status"
75         
76         # List of operator properties, the attributes will be assigned
77         # to the class instance from the operator settings before calling.
78         
79         __props__ = []
80         
81         def poll(self, context):
82                 return True
83         
84         def execute(self, context):
85                 netsettings = context.scene.network_render
86                 conn = clientConnection(context.scene)
87
88                 if conn:
89                         conn.request("GET", "/status")
90                         
91                         response = conn.getresponse()
92                         print( response.status, response.reason )
93                         
94                         jobs = (netrender.model.RenderJob.materialize(j) for j in eval(str(response.read(), encoding='utf8')))
95                         
96                         while(len(netsettings.jobs) > 0):
97                                 netsettings.jobs.remove(0)
98                         
99                         bpy.data.netrender_jobs = []
100                         
101                         for j in jobs:
102                                 bpy.data.netrender_jobs.append(j)
103                                 netsettings.jobs.add()
104                                 job = netsettings.jobs[-1]
105                                 
106                                 j.results = j.framesStatus() # cache frame status
107                                 
108                                 job.name = j.name
109                 
110                 return ('FINISHED',)
111         
112         def invoke(self, context, event):
113                 return self.execute(context)
114
115 @rnaOperator
116 class RENDER_OT_netclientblacklistslave(bpy.types.Operator):
117         '''Operator documentation text, will be used for the operator tooltip and python docs.'''
118         __idname__ = "render.netclientblacklistslave"
119         __label__ = "Client Blacklist Slave"
120         
121         # List of operator properties, the attributes will be assigned
122         # to the class instance from the operator settings before calling.
123         
124         __props__ = []
125         
126         def poll(self, context):
127                 return True
128         
129         def execute(self, context):
130                 netsettings = context.scene.network_render
131                 
132                 if netsettings.active_slave_index >= 0:
133                         
134                         # deal with data
135                         slave = bpy.data.netrender_slaves.pop(netsettings.active_slave_index)
136                         bpy.data.netrender_blacklist.append(slave)
137                         
138                         # deal with rna
139                         netsettings.slaves_blacklist.add()
140                         netsettings.slaves_blacklist[-1].name = slave.name
141                         
142                         netsettings.slaves.remove(netsettings.active_slave_index)
143                         netsettings.active_slave_index = -1
144                 
145                 return ('FINISHED',)
146         
147         def invoke(self, context, event):
148                 return self.execute(context)
149
150 @rnaOperator
151 class RENDER_OT_netclientwhitelistslave(bpy.types.Operator):
152         '''Operator documentation text, will be used for the operator tooltip and python docs.'''
153         __idname__ = "render.netclientwhitelistslave"
154         __label__ = "Client Whitelist Slave"
155         
156         # List of operator properties, the attributes will be assigned
157         # to the class instance from the operator settings before calling.
158         
159         __props__ = []
160         
161         def poll(self, context):
162                 return True
163         
164         def execute(self, context):
165                 netsettings = context.scene.network_render
166                 
167                 if netsettings.active_blacklisted_slave_index >= 0:
168                         
169                         # deal with data
170                         slave = bpy.data.netrender_blacklist.pop(netsettings.active_blacklisted_slave_index)
171                         bpy.data.netrender_slaves.append(slave)
172                         
173                         # deal with rna
174                         netsettings.slaves.add()
175                         netsettings.slaves[-1].name = slave.name
176                         
177                         netsettings.slaves_blacklist.remove(netsettings.active_blacklisted_slave_index)
178                         netsettings.active_blacklisted_slave_index = -1
179                 
180                 return ('FINISHED',)
181         
182         def invoke(self, context, event):
183                 return self.execute(context)
184
185
186 @rnaOperator
187 class RENDER_OT_netclientslaves(bpy.types.Operator):
188         '''Refresh status about available Render slaves'''
189         __idname__ = "render.netclientslaves"
190         __label__ = "Client Slaves"
191         
192         # List of operator properties, the attributes will be assigned
193         # to the class instance from the operator settings before calling.
194         
195         __props__ = []
196         
197         def poll(self, context):
198                 return True
199         
200         def execute(self, context):
201                 netsettings = context.scene.network_render
202                 conn = clientConnection(context.scene)
203                 
204                 if conn:
205                         conn.request("GET", "/slaves")
206                         
207                         response = conn.getresponse()
208                         print( response.status, response.reason )
209                         
210                         slaves = (netrender.model.RenderSlave.materialize(s) for s in eval(str(response.read(), encoding='utf8')))
211                         
212                         while(len(netsettings.slaves) > 0):
213                                 netsettings.slaves.remove(0)
214                         
215                         bpy.data.netrender_slaves = []
216                         
217                         for s in slaves:
218                                 for i in range(len(bpy.data.netrender_blacklist)):
219                                         slave = bpy.data.netrender_blacklist[i]
220                                         if slave.id == s.id:
221                                                 bpy.data.netrender_blacklist[i] = s
222                                                 netsettings.slaves_blacklist[i].name = s.name
223                                                 break
224                                 else:
225                                         bpy.data.netrender_slaves.append(s)
226                                         
227                                         netsettings.slaves.add()
228                                         slave = netsettings.slaves[-1]
229                                         slave.name = s.name
230                 
231                 return ('FINISHED',)
232         
233         def invoke(self, context, event):
234                 return self.execute(context)
235
236 @rnaOperator
237 class RENDER_OT_netclientcancel(bpy.types.Operator):
238         '''Cancel the selected network rendering job.'''
239         __idname__ = "render.netclientcancel"
240         __label__ = "Client Cancel"
241         
242         # List of operator properties, the attributes will be assigned
243         # to the class instance from the operator settings before calling.
244         
245         __props__ = []
246         
247         def poll(self, context):
248                 netsettings = context.scene.network_render
249                 return netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0
250                 
251         def execute(self, context):
252                 netsettings = context.scene.network_render
253                 conn = clientConnection(context.scene)
254                 
255                 if conn:
256                         job = bpy.data.netrender_jobs[netsettings.active_job_index]
257                         
258                         conn.request("POST", "/cancel", headers={"job-id":job.id})
259                         
260                         response = conn.getresponse()
261                         print( response.status, response.reason )
262
263                         netsettings.jobs.remove(netsettings.active_job_index)
264                 
265                 return ('FINISHED',)
266         
267         def invoke(self, context, event):
268                 return self.execute(context)
269         
270 @rnaOperator
271 class RENDER_OT_netclientcancelall(bpy.types.Operator):
272         '''Cancel all running network rendering jobs.'''
273         __idname__ = "render.netclientcancelall"
274         __label__ = "Client Cancel All"
275         
276         # List of operator properties, the attributes will be assigned
277         # to the class instance from the operator settings before calling.
278         
279         __props__ = []
280         
281         def poll(self, context):
282                 return True
283                 
284         def execute(self, context):
285                 netsettings = context.scene.network_render
286                 conn = clientConnection(context.scene)
287                 
288                 if conn:
289                         conn.request("POST", "/clear")
290                         
291                         response = conn.getresponse()
292                         print( response.status, response.reason )
293                 
294                         while(len(netsettings.jobs) > 0):
295                                 netsettings.jobs.remove(0)
296
297                 return ('FINISHED',)
298         
299         def invoke(self, context, event):
300                 return self.execute(context)
301
302 @rnaOperator
303 class netclientdownload(bpy.types.Operator):
304         '''Download render results from the network'''
305         __idname__ = "render.netclientdownload"
306         __label__ = "Client Download"
307         
308         # List of operator properties, the attributes will be assigned
309         # to the class instance from the operator settings before calling.
310         
311         __props__ = []
312         
313         def poll(self, context):
314                 netsettings = context.scene.network_render
315                 return netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0
316                 
317         def execute(self, context):
318                 netsettings = context.scene.network_render
319                 rd = context.scene.render_data
320                 
321                 conn = clientConnection(context.scene)
322                 
323                 if conn:
324                         job = bpy.data.netrender_jobs[netsettings.active_job_index]
325                         
326                         for frame in job.frames:
327                                 client.requestResult(conn, job.id, frame.number)
328                                 response = conn.getresponse()
329                 
330                                 if response.status != http.client.OK:
331                                         print("missing", frame.number)
332                                         continue
333                                 
334                                 print("got back", frame.number)
335                                 
336                                 f = open(netsettings.path + "%06d" % frame.number + ".exr", "wb")
337                                 buf = response.read(1024)
338                                 
339                                 while buf:
340                                         f.write(buf)
341                                         buf = response.read(1024)
342                                 
343                                 f.close()
344                         
345                         conn.close()
346                 
347                 return ('FINISHED',)
348         
349         def invoke(self, context, event):
350                 return self.execute(context)
351
352 @rnaOperator
353 class netclientscan(bpy.types.Operator):
354         '''Operator documentation text, will be used for the operator tooltip and python docs.'''
355         __idname__ = "render.netclientscan"
356         __label__ = "Client Scan"
357         
358         # List of operator properties, the attributes will be assigned
359         # to the class instance from the operator settings before calling.
360         
361         __props__ = []
362         
363         def poll(self, context):
364                 return True
365                 
366         def execute(self, context):
367                 netsettings = context.scene.network_render
368                 
369                 try:
370                         s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
371                         s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
372                         s.settimeout(30)
373         
374                         s.bind(('', 8000))
375                         
376                         buf, address = s.recvfrom(64)
377                         
378                         print("received:", buf)
379                         
380                         netsettings.server_address = address[0]
381                         netsettings.server_port = int(str(buf, encoding='utf8'))
382                 except socket.timeout:
383                         print("no server info")
384                 
385                 return ('FINISHED',)
386         
387         def invoke(self, context, event):
388                 return self.execute(context)
389
390 @rnaOperator
391 class netclientweb(bpy.types.Operator):
392         '''Open new window with information about running rendering jobs'''
393         __idname__ = "render.netclientweb"
394         __label__ = "Open Master Monitor"
395         
396         # List of operator properties, the attributes will be assigned
397         # to the class instance from the operator settings before calling.
398         
399         __props__ = []
400         
401         def poll(self, context):
402                 return True
403                 
404         def execute(self, context):
405                 netsettings = context.scene.network_render
406                 
407                 
408                 # open connection to make sure server exists
409                 conn = clientConnection(context.scene)
410                 
411                 if conn:
412                         conn.close()
413                         
414                         webbrowser.open("http://%s:%i" % (netsettings.server_address, netsettings.server_port))
415                 
416                 return ('FINISHED',)
417         
418         def invoke(self, context, event):
419                 return self.execute(context)