PageRenderTime 60ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/youtubed2x_lib/settings.py

https://github.com/Ryochan7/YouTubed-2x
Python | 386 lines | 356 code | 25 blank | 5 comment | 37 complexity | e71d29e5d89b4e7e30cf286f84c1f1fc MD5 | raw file
  1. import os
  2. import sys
  3. import ConfigParser
  4. from videoitem import VideoItem
  5. from other import WINDOWS, UserDirectoryIndex
  6. if WINDOWS:
  7. import ctypes
  8. class Settings (object):
  9. # CSIDL_MYVIDEO environment variable corresponds to user's My Videos
  10. # Directory
  11. CSIDL_MYVIDEO = 14
  12. # Alternative environment variable for all users. Use if CSIDL_MYVIDEO
  13. # is not defined
  14. CSIDL_COMMON_VIDEO = 55
  15. BUFFER_MAXLENGTH = 300
  16. class InvalidConfig (Exception):
  17. pass
  18. def __init__ (self):
  19. self.setDefaults ()
  20. def readConfigFile (self):
  21. if not os.path.exists (self.config_file_location):
  22. print "Config file does not exist. Skipping."
  23. return
  24. string_keys = ("output_dir", "format", "ffmpeg_location", "proxy_server")
  25. int_keys = ("vbitrate", "abitrate", "output_res", "proxy_port", "process_limit", "download_speed_limit")
  26. boolean_keys = ("keep_flv_files", "overwrite", "transcode", "sitedirs", "use_proxy", "auto_download")
  27. config = ConfigParser.ConfigParser ()
  28. try:
  29. config.read (self.config_file_location)
  30. except ConfigParser.MissingSectionHeaderError:
  31. raise self.__class__.InvalidConfig ("No header is defined")
  32. except IOError:
  33. raise self.__class__.InvalidConfig ("Could not read config file")
  34. if not config.has_section ("settings"):
  35. raise self.__class__.InvalidConfig ("Settings header is missing")
  36. for option in config.options ("settings"):
  37. if option in string_keys:
  38. setattr (self, option, config.get ("settings", option))
  39. elif option in int_keys:
  40. try:
  41. setattr (self, option, config.getint ("settings", option))
  42. except ValueError as exception:
  43. raise self.__class__.InvalidConfig ("%s" % exception.args)
  44. except TypeError as exception:
  45. raise self.__class__.InvalidConfig ("%s" % exception.args)
  46. elif option in boolean_keys:
  47. try:
  48. setattr (self, option, config.getboolean ("settings", option))
  49. except ValueError as exception:
  50. raise self.__class__.InvalidConfig ("%s" % exception.args)
  51. except TypeError as exception:
  52. raise self.__class__.InvalidConfig ("%s" % exception.args)
  53. if not os.path.isdir (self.output_dir):
  54. raise self.__class__.InvalidConfig ("Directory \"%s\" does not exist" % self.output_dir)
  55. if not os.path.exists (self.ffmpeg_location):
  56. raise self.__class__.InvalidConfig ("FFmpeg location \"%s\" is invalid" % self.ffmpeg_location)
  57. return
  58. def writeConfigFile (self):
  59. if not os.path.isdir (self.config_dir):
  60. os.mkdir (self.config_dir)
  61. try:
  62. file = open (self.config_file_location, "w")
  63. except (IOError, OSError):
  64. print >> sys.stderr, "Could not write config file."
  65. return
  66. config = ConfigParser.ConfigParser ()
  67. config.add_section ("settings")
  68. config.set ("settings", "output_dir", self.output_dir)
  69. config.set ("settings", "keep_flv_files", self.keep_flv_files)
  70. if self.format == VideoItem.AVI_FILE:
  71. config.set ("settings", "format", "avi")
  72. elif self.format == VideoItem.MP4_AVI_FILE:
  73. config.set ("settings", "format", "mpeg4")
  74. elif self.format == VideoItem.MP3_FILE:
  75. config.set ("settings", "format", "mp3")
  76. config.set ("settings", "vbitrate", self.vbitrate)
  77. config.set ("settings", "abitrate", self.abitrate)
  78. config.set ("settings", "overwrite", self.overwrite)
  79. config.set ("settings", "transcode", self.transcode)
  80. config.set ("settings", "ffmpeg_location", self.ffmpeg_location)
  81. config.set ("settings", "sitedirs", self.sitedirs)
  82. config.set ("settings", "output_res", self.output_res)
  83. config.set ("settings", "use_proxy", self.use_proxy)
  84. if self.proxy_server and self.proxy_port:
  85. config.set ("settings", "proxy_server", self.proxy_server)
  86. config.set ("settings", "proxy_port", self.proxy_port)
  87. config.set ("settings", "process_limit", self.process_limit)
  88. config.set ("settings", "auto_download", self.auto_download)
  89. config.set ("settings", "download_speed_limit", self.download_speed_limit)
  90. config.write (file)
  91. file.close ()
  92. return
  93. def setDefaults (self):
  94. self.vbitrate = 384
  95. self.abitrate = 128
  96. self.format = VideoItem.MP4_AVI_FILE
  97. self.transcode = True
  98. self.overwrite = False
  99. self.keep_flv_files = True
  100. if WINDOWS:
  101. dll = ctypes.windll.shell32
  102. buf = ctypes.create_unicode_buffer (self.BUFFER_MAXLENGTH)
  103. dll.SHGetSpecialFolderPathW (None, buf, self.CSIDL_MYVIDEO, False)
  104. # CSIDL_MYVIDEO is not defined. Try CSIDL_COMMON_VIDEO instead
  105. if not buf.value:
  106. dll.SHGetSpecialFolderPathW (None, buf, self.CSIDL_COMMON_VIDEO, False)
  107. self.output_dir = buf.value
  108. else:
  109. self.output_dir = os.path.join (os.path.expanduser ("~"), "Videos")
  110. self.ffmpeg_location = os.path.join (sys.prefix, "bin", "ffmpeg")
  111. self.sitedirs = False
  112. if not os.path.isdir (self.output_dir):
  113. os.mkdir (self.output_dir)
  114. self.config_dir = UserDirectoryIndex.config_dir
  115. self.config_file_location = os.path.join (self.config_dir, "config.conf")
  116. possible_paths = (os.path.join (sys.prefix, "local", "bin"), os.path.join (sys.prefix, "bin"),)
  117. if not os.path.exists (self.ffmpeg_location):
  118. if not WINDOWS:
  119. for path in possible_paths:
  120. if os.path.exists (os.path.join (path, "ffmpeg")):
  121. self.ffmpeg_location = os.path.join (path, "ffmpeg")
  122. break
  123. elif os.path.exists (os.path.join ("bin", "ffmpeg.exe")):
  124. self.ffmpeg_location = os.path.abspath (os.path.join ("bin", "ffmpeg.exe"))
  125. self.output_res = VideoItem.RES_320
  126. self.use_proxy = False
  127. self.proxy_server = ""
  128. self.proxy_port = 1
  129. self.process_limit = 4
  130. self.auto_download = True
  131. self.download_speed_limit = 0 # In KBps. 0 means no limit
  132. def _get_output_dir (self):
  133. return self._output_dir
  134. def _set_output_dir (self, value):
  135. if isinstance (value, (str, unicode)):
  136. self._output_dir = value
  137. else:
  138. raise TypeError ("""output_dir value must be passed as an"""
  139. """ascii or unicode string""")
  140. output_dir = property (_get_output_dir, _set_output_dir)
  141. def _get_vbitrate (self):
  142. return self._vbitrate
  143. def _set_vbitrate (self, value):
  144. if isinstance (value, int) and value <= 2000 and (value % 32) == 0:
  145. self._vbitrate = value
  146. elif isinstance (value, int) and value <= 2000:
  147. raise ValueError ("vbitrate value must be divisible by 8")
  148. elif is_int and (value % 8) == 0:
  149. raise ValueError ("vbitrate value passed greater than 2000")
  150. else:
  151. raise TypeError ("vbitrate must be an integer")
  152. vbitrate = property (_get_vbitrate, _set_vbitrate)
  153. def _get_abitrate (self):
  154. return self._abitrate
  155. def _set_abitrate (self, value):
  156. is_int = isinstance (value, int)
  157. if is_int and value <= 384 and (value % 32) == 0:
  158. self._abitrate = value
  159. elif is_int and value <= 384:
  160. raise ValueError ("abitrate must be divisible by 32")
  161. elif is_int and (value % 32) == 0:
  162. raise ValueError ("abitrate value passed greater than 384")
  163. else:
  164. raise TypeError ("abitrate must be an integer")
  165. abitrate = property (_get_abitrate, _set_abitrate)
  166. def _get_format (self):
  167. return self._format
  168. def _set_format (self, value):
  169. if isinstance (value, str):
  170. if value == "avi":
  171. self._format = VideoItem.AVI_FILE
  172. elif value == "mpeg4":
  173. self._format = VideoItem.MP4_AVI_FILE
  174. elif value == "mp3":
  175. self._format = VideoItem.MP3_FILE
  176. else:
  177. raise ValueError ("Invalid format string passed")
  178. elif isinstance (value, int):
  179. if value in VideoItem.VIDEO_FORMATS or value in VideoItem.AUDIO_FORMATS:
  180. self._format = value
  181. else:
  182. raise ValueError ("Invalid format integer passed")
  183. else:
  184. raise TypeError ("format attribute is invalid")
  185. format = property (_get_format, _set_format)
  186. def _get_transcode (self):
  187. return self._transcode
  188. def _set_transcode (self, value):
  189. if isinstance (value, bool):
  190. self._transcode = value
  191. else:
  192. raise TypeError ("transcode value must be a boolean")
  193. transcode = property (_get_transcode, _set_transcode)
  194. def _get_overwrite (self):
  195. return self._overwrite
  196. def _set_overwrite (self, value):
  197. if isinstance (value, bool):
  198. self._overwrite = value
  199. else:
  200. raise TypeError ("overwrite value must be a boolean")
  201. overwrite = property (_get_overwrite, _set_overwrite)
  202. def _get_keep_flv_files (self):
  203. return self._keep_flv_files
  204. def _set_keep_flv_files (self, value):
  205. if isinstance (value, bool):
  206. self._keep_flv_files = value
  207. else:
  208. raise TypeError ("keep_flv_files value must be a boolean")
  209. keep_flv_files = property (_get_keep_flv_files, _set_keep_flv_files)
  210. def _get_ffmpeg_location (self):
  211. return self._ffmpeg_location
  212. def _set_ffmpeg_location (self, value):
  213. if isinstance (value, str):
  214. self._ffmpeg_location = value
  215. else:
  216. raise TypeError ("ffmpeg location must be given as a string")
  217. ffmpeg_location = property (_get_ffmpeg_location, _set_ffmpeg_location)
  218. def _get_sitedirs (self):
  219. return self._sitedirs
  220. def _set_sitedirs (self, value):
  221. if isinstance (value, bool):
  222. self._sitedirs = value
  223. else:
  224. raise TypeError ("sitedirs value must be a boolean")
  225. sitedirs = property (_get_sitedirs, _set_sitedirs)
  226. def _get_config_dir (self):
  227. return self._config_dir
  228. def _set_config_dir (self, value):
  229. if isinstance (value, str):
  230. self._config_dir = value
  231. else:
  232. raise TypeError ("config_dir location must be given as a string")
  233. config_dir = property (_get_config_dir, _set_config_dir)
  234. def _get_config_file_location (self):
  235. return self._config_file_location
  236. def _set_config_file_location (self, value):
  237. if isinstance (value, str):
  238. self._config_file_location = value
  239. else:
  240. raise TypeError ("config_file_location location must be given as a string")
  241. config_file_location = property (_get_config_file_location, _set_config_file_location)
  242. def _get_output_res (self):
  243. return self._output_res
  244. def _set_output_res (self, value):
  245. is_int = isinstance (value, int)
  246. if is_int and (value == VideoItem.RES_320 or value == VideoItem.RES_640):
  247. self._output_res = value
  248. elif is_int:
  249. raise ValueError ("output_res is not a valid resolution")
  250. else:
  251. raise TypeError ("output_res must be an integer")
  252. output_res = property (_get_output_res, _set_output_res)
  253. def _get_use_proxy (self):
  254. return self._use_proxy
  255. def _set_use_proxy (self, value):
  256. if isinstance (value, bool):
  257. self._use_proxy = value
  258. else:
  259. raise TypeError ("use_proxy value must be a boolean")
  260. use_proxy = property (_get_use_proxy, _set_use_proxy)
  261. def _get_proxy_server (self):
  262. return self._proxy_server
  263. def _set_proxy_server (self, value):
  264. if isinstance (value, str):
  265. self._proxy_server = value
  266. else:
  267. raise TypeError ("proxy_server must be given as a string")
  268. proxy_server = property (_get_proxy_server, _set_proxy_server)
  269. def _get_proxy_port (self):
  270. return self._proxy_port
  271. def _set_proxy_port (self, value):
  272. if isinstance (value, int):
  273. self._proxy_port = value
  274. else:
  275. raise TypeError ("proxy_port must be an integer")
  276. proxy_port = property (_get_proxy_port, _set_proxy_port)
  277. def _get_process_limit (self):
  278. return self._process_limit
  279. def _set_process_limit (self, value):
  280. is_int = isinstance (value, int)
  281. if is_int and value >= 0:
  282. self._process_limit = value
  283. elif is_int:
  284. raise ValueError ("process_limit is invalid. Must be >= 0")
  285. else:
  286. raise TypeError ("process_limit must be an integer")
  287. process_limit = property (_get_process_limit, _set_process_limit)
  288. def _get_auto_download (self):
  289. return self._auto_download
  290. def _set_auto_download (self, value):
  291. if isinstance (value, bool):
  292. self._auto_download = value
  293. else:
  294. raise TypeError ("auto_download value must be a boolean")
  295. auto_download = property (_get_auto_download, _set_auto_download)
  296. def _get_download_speed_limit (self):
  297. return self._download_speed_limit
  298. def _set_download_speed_limit (self, value):
  299. if isinstance (value, (int, long,)) and value >= 0:
  300. self._download_speed_limit = value
  301. elif value < 0:
  302. raise TypeError ("download_speed_limit value must be 0 or greater. Passed value: %s" % value)
  303. else:
  304. raise TypeError ("download_speed_limit value must be an int or long")
  305. download_speed_limit = property (_get_download_speed_limit, _set_download_speed_limit)