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.

135 lines
2.8 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 == 'CD_TEXT':
  53. state = 1
  54. if track == 0:
  55. textobj = r
  56. elif key == 'TRACK':
  57. track += 1
  58. textobj = { 'track': track }
  59. r['tracks'][track] = textobj
  60. elif key == 'TWO_CHANNEL_AUDIO':
  61. textobj['channels'] = 2
  62. elif key == 'FOUR_CHANNEL_AUDIO':
  63. textobj['channels'] = 4
  64. elif key == 'ISRC':
  65. textobj['isrc'] = decodestr(i, i.index('"') + 1)
  66. elif key == 'COPY':
  67. textobj['copy'] = True
  68. elif items[0] == 'NO' and items[1] == 'COPY':
  69. textobj['copy'] = False
  70. elif key == 'PRE_EMPHASIS':
  71. textobj['preemphasis'] = True
  72. elif items[0] == 'NO' and items[1] == 'PRE_EMPHASIS':
  73. textobj['preemphasis'] = False
  74. elif key == 'FILE':
  75. pass # XXX
  76. elif key == 'START':
  77. pass # XXX
  78. elif key == '//':
  79. pass
  80. else:
  81. raise ValueError('unknown line: %s' % `i`)
  82. elif state == 1:
  83. if key == 'LANGUAGE_MAP':
  84. state = 2
  85. elif key == 'LANGUAGE':
  86. state = 3
  87. langobj = textobj
  88. # XXX - don't try to use more than one!
  89. #lang = items[1].strip()
  90. #textobj[langmap[lang]] = langobj
  91. elif key == '}':
  92. textobj = None
  93. state = 0
  94. elif state == 2:
  95. if key == '}':
  96. state = 1
  97. else:
  98. key, value = (x.strip() for x in i.split(':'))
  99. value = int(value)
  100. langmap[key] = value
  101. elif state == 3:
  102. if key == '}':
  103. langobj = None
  104. state = 1
  105. else:
  106. curl = i.find('{')
  107. dquo = i.find('"')
  108. if curl != -1 and curl < dquo:
  109. val = i[i.index('{') + 1:i.index('}')]
  110. val = ''.join(chr(int(x)) for x in
  111. val.split(','))
  112. else:
  113. if dquo == -1:
  114. raise ValueError('no dquote')
  115. val = decodestr(i, dquo + 1)
  116. langobj[key] = val
  117. return r
  118. if __name__ == '__main__':
  119. import sys
  120. for i in sys.argv[1:]:
  121. print 'file:', `i`
  122. print parsetoc(open(i).read())