something something managing too many camera stuff
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

utils.py 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import datetime
  2. import hashlib
  3. import os
  4. import subprocess
  5. from os.path import splitext
  6. from flask import current_app
  7. from flask_security import current_user
  8. from models import db, Role, Logging, Config, UserLogging
  9. IMAGES = tuple("jpg jpe jpeg png gif".split())
  10. def gcfg():
  11. _config = Config.query.one()
  12. if not _config:
  13. return {"app_name": "ree2bits"}
  14. return {"app_name": _config.app_name}
  15. class InvalidUsage(Exception):
  16. status_code = 400
  17. def __init__(self, message, status_code=None, payload=None):
  18. Exception.__init__(self)
  19. self.message = message
  20. if status_code is not None:
  21. self.status_code = status_code
  22. self.payload = payload
  23. def to_dict(self):
  24. rv = dict(self.payload or ())
  25. rv["message"] = self.message
  26. rv["status"] = "error"
  27. rv["code"] = self.status_code
  28. return rv
  29. def is_admin():
  30. adm = Role.query.filter(Role.name == "admin").first()
  31. if not current_user or not current_user.is_authenticated or not adm:
  32. return False
  33. if adm in current_user.roles:
  34. return True
  35. return False
  36. def add_log(category, level, message):
  37. if not category or not level or not message:
  38. print("!! Fatal error in add_log() one of three variables not set")
  39. print("[LOG][{0}][{1}] {2}".format(level.upper(), category, message))
  40. a = Logging(category=category, level=level.upper(), message=message)
  41. db.session.add(a)
  42. db.session.commit()
  43. # categories used, they are used to map the item_id to the right model
  44. # - sounds
  45. # - albums
  46. # - user
  47. # - global
  48. def add_user_log(item, user, category, level, message):
  49. if not category or not level or not message or not item:
  50. print("!! Fatal error in add_user_log() one of three variables not set")
  51. print("[LOG][{0}][{1}][u:{2}i:{3}] {4}".format(level.upper(), category, user, item, message))
  52. a = UserLogging(category=category, level=level.upper(), message=message, item_id=item, user_id=user)
  53. db.session.add(a)
  54. db.session.commit()
  55. def duration_elapsed_human(seconds):
  56. print(seconds)
  57. seconds = round(seconds)
  58. minutes, seconds = divmod(seconds, 60)
  59. hours, minutes = divmod(minutes, 60)
  60. days, hours = divmod(hours, 24)
  61. years, days = divmod(days, 365.242199)
  62. minutes = int(minutes)
  63. hours = int(hours)
  64. days = int(days)
  65. years = int(years)
  66. if years > 0:
  67. return "%d y" % years
  68. elif days > 0:
  69. return "%d d" % days
  70. elif hours > 0:
  71. return "%d h" % hours + "s" * (hours != 1)
  72. elif minutes > 0:
  73. return "%d mn" % minutes + "s" * (minutes != 1)
  74. else:
  75. return "right now"
  76. def duration_song_human(seconds):
  77. if seconds is None:
  78. return "error"
  79. seconds = float(seconds)
  80. seconds = seconds
  81. minutes, seconds = divmod(seconds, 60)
  82. hours, minutes = divmod(minutes, 60)
  83. days, hours = divmod(hours, 24)
  84. years, days = divmod(days, 365.242199)
  85. minutes = int(minutes)
  86. hours = int(hours)
  87. days = int(days)
  88. years = int(years)
  89. if years > 0:
  90. return "%d year" % years + "s" * (years != 1)
  91. elif days > 0:
  92. return "%d day" % days + "s" * (days != 1)
  93. elif hours > 0:
  94. return "%d hour" % hours + "s" * (hours != 1)
  95. elif minutes > 0:
  96. return "%d mn" % minutes + "s" * (minutes != 1)
  97. else:
  98. return "%.2f sec" % seconds + "s" * (seconds != 1)
  99. def get_waveform(filename):
  100. binary = current_app.config["AUDIOWAVEFORM_BIN"]
  101. if not os.path.exists(binary) or not os.path.exists(filename):
  102. add_log("AUDIOWAVEFORM", "ERROR", "Filename {0} or binary {1} invalid".format(filename, binary))
  103. return None
  104. tmpjson = "{0}.json".format(filename)
  105. cmd = [binary, "-i", filename, "--pixels-per-second", "10", "-b", "8", "-o", tmpjson]
  106. """
  107. Failed: Can't generate "xxx" from "xxx"
  108. OK:
  109. Input file: piano2.wav
  110. Frames: 302712
  111. Sample rate: 48000 Hz
  112. Channels: 2
  113. Format: 0x10002
  114. Sections: 1
  115. Seekable: yes
  116. Generating waveform data...
  117. Samples per pixel: 4800
  118. Input channels: 2
  119. Done: 100%
  120. Read 302712 frames
  121. Generated 64 points
  122. Writing output file: some-file.json
  123. """
  124. try:
  125. process = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  126. if not process:
  127. add_log("AUDIOWAVEFORM", "ERROR", "Subprocess returned None")
  128. return None
  129. except subprocess.CalledProcessError as e:
  130. add_log("AUDIOWAVEFORM", "ERROR", "Process error: {0}".format(e))
  131. return None
  132. print("- Command ran with: {0}".format(process.args))
  133. if process.stderr.startswith(b"Can't generate"):
  134. add_log("AUDIOWAVEFORM", "ERROR", "Process error: {0}".format(process.stderr))
  135. return None
  136. with open(tmpjson, "r") as f:
  137. json = f.readlines()
  138. os.unlink(tmpjson)
  139. if isinstance(json, list):
  140. json = json[0].rstrip()
  141. return json
  142. def create_png_waveform(fn_audio, fn_png):
  143. binary = current_app.config["AUDIOWAVEFORM_BIN"]
  144. if not os.path.exists(binary) or not os.path.exists(fn_audio):
  145. add_log("AUDIOWAVEFORM_PNG", "ERROR", "Filename {0} or binary {1} invalid".format(fn_audio, binary))
  146. return None
  147. pngwf = "{0}.png".format(fn_png)
  148. cmd = [binary, "-i", fn_audio, "--width", "384", "--height", "64", "--no-axis-labels", "-o", pngwf]
  149. try:
  150. process = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  151. if not process:
  152. add_log("AUDIOWAVEFORM_PNG", "ERROR", "Subprocess returned None")
  153. return None
  154. except subprocess.CalledProcessError as e:
  155. add_log("AUDIOWAVEFORM_PNG", "ERROR", "Process error: {0}".format(e))
  156. return None
  157. print("- Command ran with: {0}".format(process.args))
  158. if process.stderr.startswith(b"Can't generate"):
  159. add_log("AUDIOWAVEFORM_PNG", "ERROR", "Process error: {0}".format(process.stderr))
  160. return None
  161. return True
  162. def get_hashed_filename(filename):
  163. f_n, f_e = splitext(filename)
  164. fs_fname = hashlib.sha256()
  165. hashed_format = "%s-%s" % (f_n, datetime.datetime.now())
  166. fs_fname.update(hashed_format.encode("utf-8"))
  167. fs_fname = fs_fname.hexdigest()
  168. return fs_fname + f_e