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.

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