A Python UPnP Media Server
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.

140 lines
3.0 KiB

  1. #!/usr/bin/env python
  2. import string
  3. types = frozenset([ 'CD_DA', 'CD_ROM', 'CD_ROMXA'])
  4. def decodestr(i, pos):
  5. return decodestrend(i, pos)[0]
  6. def decodestrend(i, pos):
  7. r = []
  8. bspos = None
  9. dqpos = None
  10. while True:
  11. if bspos is None or bspos == -1 or bspos < pos:
  12. bspos = i.find('\\', pos)
  13. if dqpos is None or dqpos < pos:
  14. dqpos = i.index('"', pos)
  15. if bspos >= 0 and bspos < dqpos:
  16. r.append(i[pos:bspos])
  17. c = i[bspos + 1]
  18. if c == '"':
  19. r.append('"')
  20. pos = bspos + 2
  21. elif c in string.digits:
  22. r.append(chr(int(i[bspos + 1:bspos + 4], 8)))
  23. pos = bspos + 4
  24. elif c == 'n':
  25. r.append('\n')
  26. pos = bspos + 2
  27. else:
  28. raise ValueError('unknown escape char: %s' % repr(c))
  29. else:
  30. r.append(i[pos:dqpos])
  31. break
  32. return ''.join(r), dqpos
  33. def parsetoc(toc):
  34. # state machine info:
  35. # 0: header
  36. # 1: in CD_TEXT
  37. # 2: in LANGUAGE_MAP
  38. # 3: in LANGUAGE
  39. r = { 'tracks': {} }
  40. langmap = {}
  41. state = 0
  42. curlang = None
  43. textobj = None
  44. langobj = None
  45. track = 0
  46. for i in toc.split('\n'):
  47. i = i.strip()
  48. if not i:
  49. continue
  50. items = i.split()
  51. key = items[0]
  52. if state == 0:
  53. if i in types:
  54. r['type'] = i
  55. elif key == 'CATALOG':
  56. r['catalog'] = decodestr(i, i.index('"') + 1)
  57. elif key == 'CD_TEXT':
  58. state = 1
  59. if track == 0:
  60. textobj = r
  61. elif key == 'TRACK':
  62. track += 1
  63. textobj = { 'track': track }
  64. r['tracks'][track] = textobj
  65. elif key == 'TWO_CHANNEL_AUDIO':
  66. textobj['channels'] = 2
  67. elif key == 'FOUR_CHANNEL_AUDIO':
  68. textobj['channels'] = 4
  69. elif key == 'ISRC':
  70. textobj['isrc'] = decodestr(i, i.index('"') + 1)
  71. elif key == 'COPY':
  72. textobj['copy'] = True
  73. elif items[0] == 'NO' and items[1] == 'COPY':
  74. textobj['copy'] = False
  75. elif key == 'PRE_EMPHASIS':
  76. textobj['preemphasis'] = True
  77. elif items[0] == 'NO' and items[1] == 'PRE_EMPHASIS':
  78. textobj['preemphasis'] = False
  79. elif key == 'FILE':
  80. pass # XXX
  81. elif key == 'START':
  82. pass # XXX
  83. elif key == '//':
  84. pass
  85. else:
  86. raise ValueError('unknown line: %s' % repr(i))
  87. elif state == 1:
  88. if key == 'LANGUAGE_MAP':
  89. state = 2
  90. elif key == 'LANGUAGE':
  91. state = 3
  92. langobj = textobj
  93. # XXX - don't try to use more than one!
  94. #lang = items[1].strip()
  95. #textobj[langmap[lang]] = langobj
  96. elif key == '}':
  97. textobj = None
  98. state = 0
  99. elif state == 2:
  100. if key == '}':
  101. state = 1
  102. else:
  103. key, value = (x.strip() for x in i.split(':'))
  104. value = int(value)
  105. langmap[key] = value
  106. elif state == 3:
  107. if key == '}':
  108. langobj = None
  109. state = 1
  110. else:
  111. curl = i.find('{')
  112. dquo = i.find('"')
  113. if curl != -1 and curl < dquo:
  114. val = i[i.index('{') + 1:i.index('}')]
  115. val = ''.join(chr(int(x)) for x in
  116. val.split(','))
  117. else:
  118. if dquo == -1:
  119. raise ValueError('no dquote')
  120. val = decodestr(i, dquo + 1)
  121. langobj[key] = val
  122. return r
  123. if __name__ == '__main__':
  124. import sys
  125. for i in sys.argv[1:]:
  126. print('file:', repr(i))
  127. print(parsetoc(open(i).read()))