Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/updater/src/gui/orxonox_gui_update.cc @ 3298

Last change on this file since 3298 was 3298, checked in by bensch, 19 years ago

orxonox/branches/updater: autoupdate at beginning works partly

File size: 14.2 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
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, or (at your option)
9   any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software Foundation,
18   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
19
20
21   ### File Specific:
22   main-programmer: Benjamin Grauer
23
24*/
25
26#include "orxonox_gui_update.h"
27#include <iostream>
28#include <string>
29
30#include "orxonox_gui.h"
31#include <stdio.h>
32#include <stdlib.h>
33
34using namespace std;
35
36/**
37   \brief Creates an Audio-Frame
38*/
39OrxonoxGuiUpdate::OrxonoxGuiUpdate ()
40{
41  this->getSystemInfo();
42
43  this->updateFrame = new Frame ("Update-Options:");
44  this->updateFrame->setGroupName ("update");
45  this->updateBox = new Box ('v');
46#ifdef HAVE_CURL
47
48  // the Button for autoUpdating
49  this->autoUpdate = new CheckButton ("auto update");
50  this->updateBox->fill(this->autoUpdate);
51  this->autoUpdate->setFlagName ("update", "u", 0);
52  this->autoUpdate->saveability();
53
54  this->updateSourceWindowCreate ();
55  this->updateBox->fill(this->updateSourceWindowGetButton());
56
57  this->updateDataWindowCreate ();
58  this->updateBox->fill(this->updateDataWindowGetButton());
59
60#else /* HAVE_CURL */
61  Label* noCurlLabel = new Label("since you do not have cURL,\nthis option is not availible");
62  this->updateBox->fill(noCurlLabel); 
63#endif /* HAVE_CURL */
64  this->updateFrame->fill(this->updateBox);
65
66}
67
68/**
69   \brief Return the Frame
70   \return Returns the Audio-frame
71*/
72Widget* OrxonoxGuiUpdate::getWidget ()
73{
74  return updateFrame;
75}
76
77/**
78    \brief Look what info we can get from this system
79*/
80bool OrxonoxGuiUpdate::getSystemInfo(void)
81{
82  PRINTF(3)("Grabbing system information\n");
83  tmpDir = getenv("TMPDIR");
84  if (!tmpDir)
85    tmpDir = "/tmp";
86  PRINTF(4)("Temporary directory is: %s\n", tmpDir);
87
88#ifdef __WIN32__
89  homeDir = getenv ("USERPROFILE");
90#else
91  homeDir = getenv("HOME");
92#endif
93  PRINTF(4)("Home directory is %s\n", homeDir);
94
95  installDataDir = "/usr/share/games/orxonox";
96  PRINTF(4)("Installation of orxonox-data will go to this directory: %s\n", installDataDir);
97
98  installSourceDir = "/usr/games/bin";
99  PRINTF(4)("Installation of orxonox-source will go to this directory: %s\n", installSourceDir);
100
101  userName = getenv("USER");
102  PRINTF(4)("Logged in username is: %s\n", userName);
103}
104
105#ifdef HAVE_CURL
106bool* OrxonoxGuiUpdate::checkForUpdates(void)
107{
108  PRINTF(3)("checking for new version of orxonox\n");
109  FileInfo updateFileInfo;
110  updateFileInfo.fileName = "update_info";
111  updateFileInfo.webRoot = "http://www.orxonox.ethz.ch/files/data";
112  updateFileInfo.localRoot = this->tmpDir;
113 
114  download(&updateFileInfo);
115}
116#endif /* HAVE_CURL */
117#ifdef HAVE_CURL
118/**
119   \brief Creates a window, and all it contains for the Data-update.
120*/
121void OrxonoxGuiUpdate::updateDataWindowCreate (void)
122{
123  updateDataWindow = new Window ("update orxonox::Data");   
124  updateDataBox = new Box ('v');
125
126  // the close-Button of the Update Window.
127  //  updateWindowClose = new Button ("close");
128#ifdef HAVE_GTK2
129  //  updateWindowClose->connectSignal("button_press_event", updateWindow, Window::windowClose);
130#endif /* HAVE_GTK2 */
131  //  updateWindowBox->fill(updateWindowClose);
132
133  updateDataBar = new ProgressBar ();
134  updateDataBox->fill(updateDataBar);
135
136  FileInfo* dataInfo = new FileInfo;
137  dataInfo->bar = updateDataBar;
138
139  updateDataBegin = new Button ("begin.");
140  dataInfo->stateButton = updateDataBegin;
141#ifdef HAVE_GTK2
142  dataInfo->buttonSignal = updateDataBegin->connectSignal ("button_press_event", dataInfo, updateDataFunc);
143#endif /* HAVE_GTK2 */
144  updateDataBox->fill(updateDataBegin);
145
146  updateDataWindow->fill (updateDataBox);
147
148  updateDataWindowButton = new Button ("update orxonox::Data");
149#ifdef HAVE_GTK2
150  updateDataWindowButton->connectSignal("button_press_event", updateDataWindow, Window::windowOpen);
151  updateDataWindow->connectSignal("destroy", updateDataWindow, Window::windowClose);
152  updateDataWindow->connectSignal("delete_event", updateDataWindow, Window::windowClose);
153#endif /* HAVE_GTK2 */
154
155}
156
157/**
158   \returns A Pointer to the Button of the UpdaterDataWindow
159*/
160Button* OrxonoxGuiUpdate::updateDataWindowGetButton(void)
161{
162  return updateDataWindowButton;
163}
164
165/**
166   \brief Creates a window, and all it contains for the Source-update.
167*/
168void OrxonoxGuiUpdate::updateSourceWindowCreate (void)
169{
170  // the button, that opens this Window.
171  updateSourceWindowButton = new Button ("update orxonox::Source");
172
173  // the Window itself
174  updateSourceWindow = new Window ("update orxonox::Source");
175
176  updateSourceBox = new Box ();
177
178  updateSourceBar = new ProgressBar ();
179  updateSourceBox->fill(updateSourceBar);
180  test = new Button ("increment");
181
182#ifdef HAVE_GTK2
183  test->connectSignal("button_press_event", updateSourceBar, updateSourceFunc);
184#endif /* HAVE_GTK2 */
185
186  updateSourceBox->fill(test);
187  updateSourceWindow->fill(updateSourceBox); 
188#ifdef HAVE_GTK2
189  updateSourceWindowButton->connectSignal("button_press_event", updateSourceWindow, Window::windowOpen);
190  updateSourceWindow->connectSignal("destroy", updateSourceWindow, Window::windowClose);
191  updateSourceWindow->connectSignal("delete_event", updateSourceWindow, Window::windowClose);
192#endif /* HAVE_GTK2 */
193
194}
195
196/**
197   \returns A Pointer to the Button of the UpdaterSourceWindow
198*/
199Button* OrxonoxGuiUpdate::updateSourceWindowGetButton(void)
200{
201  return updateSourceWindowButton;
202}
203
204
205#ifdef HAVE_GTK2
206/**
207   \brief updates the Data of orxonox.
208   \param w The widget, that executed this Function.
209   \param event The event that trigered this Function.
210   \param button The Button, that triggered this event.
211*/
212gint OrxonoxGuiUpdate::updateDataFunc(GtkWidget* w, GdkEventKey* event, void* info)
213{
214  FileInfo* dataInfo = (FileInfo*)info;
215
216  dataInfo->fileName = "02%20orxonox%203.mp3";
217  dataInfo->webRoot  = "http://www.orxonox.ethz.ch/files/";
218  dataInfo->localRoot = "./";
219  PRINTF(3)("Preparing to download file %s.\n", dataInfo->fileName);
220  downloadWithStyle(dataInfo);
221}
222
223/**
224   \brief updates the source of orxonox.
225   \param w The widget, that executed this Function.
226   \param event The event that trigered this Function.
227   \param button The Button, that triggered this event.
228*/
229gint OrxonoxGuiUpdate::updateSourceFunc(GtkWidget* w, GdkEventKey* event, void* bar)
230{
231  ProgressBar* tmpBar = static_cast<ProgressBar*>(bar);
232  tmpBar->setTotalSize(20);
233  tmpBar->setProgress(tmpBar->getProgress()+1);
234}
235#endif /* HAVE_GTK2 */
236
237/**
238   \brief The Function Curl calls to write out the File.
239   \param ptr A Pointer to the date to write.
240   \param size The size in bytes of one nmemb to write.
241   \param nmemb The Count of size to write.
242   \param stream Filehandler to write to.
243*/
244size_t OrxonoxGuiUpdate::curlWriteFunc (void* ptr, size_t size, size_t nmemb, FILE* stream)
245{
246  return fwrite(ptr, size, nmemb, stream);
247}
248
249/**
250   \brief The Function Curl calls to write out the File.
251   \param ptr A Pointer to the date to write to.
252   \param size The size in bytes of one nmemb to write.
253   \param nmemb The Count of size to write.
254   \param stream Filehandler to get data from.
255*/
256size_t OrxonoxGuiUpdate::curlReadFunc (void* ptr, size_t size, size_t nmemb, FILE* stream)
257{
258  return fread(ptr, size, nmemb, stream);
259}
260
261
262/**
263   \brief An update Function for the GUI, to show the progress.
264   \param Bar th ProgressBar to update
265   \param totalSize The total size of the download in bytes.
266   \param progress The current Progress of the download in bytes.
267   \param upTotal not needed
268   \param upProgress not needed
269*/
270int OrxonoxGuiUpdate::curlProgressFunc (ProgressBar* Bar, double totalSize, double progress, double upTotal, double upProgress)
271{
272  Bar->setProgress(progress);
273  Bar->setTotalSize(totalSize);
274#ifdef HAVE_GTK2
275#ifndef HAVE_PTHREAD_H
276  while(gtk_events_pending()) gtk_main_iteration();
277#endif
278#endif
279  return 0;
280}
281
282/**
283   \brief The Curl handle for only one CURL (static).
284*/
285CURL* OrxonoxGuiUpdate::curlHandle = NULL;
286
287#ifdef HAVE_PTHREAD_H
288/** \brief The download Thread ID */
289pthread_t* OrxonoxGuiUpdate::downloadThreadID = new pthread_t;
290/**   \brief The download Thread ID*/
291pthread_t* OrxonoxGuiUpdate::downloadThreadFinishID = new pthread_t;
292#endif /* HAVE_PTHREAD_H */
293/**
294   \brief A bool parameter that shows if we are downloading.
295*/
296bool OrxonoxGuiUpdate::isDownloading = false;
297
298
299/**
300   \brief Initializes a Download without displaying it.
301   \param fileInfo the FileInfo.
302
303   !! BE AWARE THIS WILL NOT BE THREADED. !!
304*/
305bool OrxonoxGuiUpdate::download(void* fileInfo)
306{
307  if (isDownloading)
308    {
309      PRINTF(2)("unable to Download. already getting some file\n");
310      return false;
311    }
312  PRINTF(3)("Downloading.\n");
313  FileInfo* info = (FileInfo*)fileInfo;
314  CURLcode res;
315  CURL* localCurl;
316  localCurl = curl_easy_init();
317  char* fileOnNet = new char [strlen(info->webRoot)+strlen(info->fileName)+2];
318  strcpy (fileOnNet, info->webRoot);
319  if (fileOnNet[strlen(fileOnNet)] != '/') //!< \todo windows-shit
320    strcat (fileOnNet, "/");
321  strcat (fileOnNet, info->fileName);
322  char* fileOnDisk = new char [strlen(info->localRoot)+strlen(info->fileName)+2];
323  strcpy (fileOnDisk, info->localRoot);
324  if (fileOnDisk[strlen(fileOnDisk)] != '/') //!< \todo windows-shit
325    strcat (fileOnDisk, "/");
326  strcat (fileOnDisk, info->fileName);
327 
328  if(localCurl)
329    {
330     
331      info->fileHandle = fopen(fileOnDisk, "w");
332     
333      curl_easy_setopt(localCurl, CURLOPT_URL, fileOnNet);
334      curl_easy_setopt(localCurl, CURLOPT_WRITEDATA, info->fileHandle);
335      curl_easy_setopt(localCurl, CURLOPT_WRITEFUNCTION, curlWriteFunc);
336      curl_easy_setopt(localCurl, CURLOPT_READFUNCTION, curlReadFunc);
337      curl_easy_setopt(localCurl, CURLOPT_NOPROGRESS, true);
338     
339      curl_easy_perform(localCurl);
340
341      curl_easy_cleanup(localCurl);
342      fclose (info->fileHandle);
343    }
344}
345
346/**
347   \brief Initializes a Download with some style.
348   \param fileInfo the FileInfo.
349   \todo release thread-lock.
350
351   Downloading with a Button that gets a different Name while downloading, and a Bar, that gets to be updated. More to be followed
352*/
353bool OrxonoxGuiUpdate::downloadWithStyle(void* fileInfo)
354{
355  if (isDownloading)
356    {
357      PRINTF(2)("unable to Download. already getting some file\n");
358      return false;
359    }
360  PRINTF(3)("Downloading.\n");
361  FileInfo* info = (FileInfo*)fileInfo;
362  CURLcode res;
363  curlHandle = curl_easy_init();
364  char* fileOnNet = new char [strlen(info->webRoot)+strlen(info->fileName)+1];
365  strcpy (fileOnNet, info->webRoot);
366  strcat (fileOnNet, info->fileName);
367  char* fileOnDisk = new char [strlen(info->localRoot)+strlen(info->fileName)+1];
368  strcpy (fileOnDisk, info->localRoot);
369  strcat (fileOnDisk, info->fileName);
370
371  if(curlHandle)
372    {
373     
374      info->fileHandle = fopen(fileOnDisk, "w");
375     
376      curl_easy_setopt(curlHandle, CURLOPT_URL, fileOnNet);
377      curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, info->fileHandle);
378      curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, curlWriteFunc);
379      curl_easy_setopt(curlHandle, CURLOPT_READFUNCTION, curlReadFunc);
380      curl_easy_setopt(curlHandle, CURLOPT_NOPROGRESS, false);
381      curl_easy_setopt(curlHandle, CURLOPT_PROGRESSFUNCTION, curlProgressFunc);
382      curl_easy_setopt(curlHandle, CURLOPT_PROGRESSDATA, info->bar);
383
384      if (!isDownloading)
385        {
386          pthread_join(*downloadThreadFinishID, NULL);
387
388#ifdef HAVE_GTK2
389          info->stateButton->disconnectSignal(info->buttonSignal);
390          info->buttonSignal = info->stateButton->connectSignal("button_press_event", info, cancelDownload);
391#endif /* HAVE_GTK2 */
392#ifdef HAVE_PTHREAD_H
393          info->stateButton->setTitle("cancel");
394#else /* HAVE_PTHREAD_H */
395          info->stateButton->setTitle("please wait");
396#endif /* HAVE_PTHREAD_H */
397         
398          //! \todo check if threads really were created.
399#ifdef HAVE_PTHREAD_H
400          pthread_create(downloadThreadID, NULL, downloadThread, info);
401          pthread_create(downloadThreadFinishID, NULL, downloadThreadFinished, info); 
402#else
403          downloadThread(info);
404          downloadThreadFinished(info);
405#endif /* HAVE_PTHREAD_H */
406         
407          //      res = curl_easy_perform(curlHandle);
408         
409          //      fclose(outfile);
410        }
411      else 
412        PRINTF(1)("thread already in use\n");
413
414    }
415  return true;
416}
417
418/**
419   \brief The downloading process (either threaded or not).
420   \param fileInfo the FileInfo.
421
422   \todo Threads get locked, if the cancel button is pressed in to small intervals.
423*/
424void* OrxonoxGuiUpdate::downloadThread(void* fileInfo)
425{
426  isDownloading = true;
427  curl_easy_perform(curlHandle);
428}
429
430/**
431   \brief Finishes a downloading process.
432   \param fileInfo the FileInfo.
433*/
434void* OrxonoxGuiUpdate::downloadThreadFinished(void* fileInfo)
435{ 
436  FileInfo* info = (FileInfo*)fileInfo;
437#ifdef HAVE_PTHREAD_H
438  pthread_join (*downloadThreadID, NULL);
439#ifdef HAVE_GTK2
440  gdk_threads_enter();
441#endif /* HAVE_GTK2 */
442#endif /* HAVE_PTHREAD_H */
443  if (curlHandle)
444    curl_easy_cleanup(curlHandle);
445 
446  PRINTF(3)("Closing the downloaded file.\n");
447  fclose(info->fileHandle);
448
449  if (isDownloading)
450    info->stateButton->setTitle("go on");
451  //  else
452  //    info->stateButton->setTitle("done");
453#ifdef HAVE_GTK2
454  info->stateButton->disconnectSignal(info->buttonSignal);
455  info->buttonSignal = info->stateButton->connectSignal("button_press_event", info, updateDataFunc);
456#endif /* HAVE_GTK2 */
457  isDownloading = false;
458#ifdef HAVE_PTHREAD_H
459#ifdef HAVE_GTK2
460  gdk_threads_leave();
461#endif /* HAVE_GTK2 */
462#endif /* HAVE_PTHREAD_H */
463
464}
465
466#ifdef HAVE_GTK2
467/**
468   \brief canceles a downloading session.
469   \param w The widget, that executed this Function.
470   \param event The event that trigered this Function.
471   \param bar The Bar, that triggered this event.
472
473   \todo canceling a session in non-threaded mode.
474*/
475gint OrxonoxGuiUpdate::cancelDownload(GtkWidget* w, GdkEventKey* event, void* bar)
476{
477#ifdef HAVE_PTHREAD_H
478  pthread_cancel(*downloadThreadID);
479#else
480  PRINTF(2)("Cannot cancle the Downloading process until after this File, because no threading was enabled");
481#endif /* HAVE_PTHREAD_H*/
482}
483#endif /* HAVE_GTK2 */
484
485#endif /* HAVE_CURL */
Note: See TracBrowser for help on using the repository browser.