1 #include <string> 2 #include "audiere.h" 3 #include "internal.h" 4 #include "mci_device.h" 5 6 7 namespace audiere { 8 9 /** 10 * Since MCI uses a global list of device aliases, this prevents name 11 * collisions. Maybe should be synchronized or volatile. 12 */ 13 static int g_song_count = 0; 14 15 16 class MCIMIDIStream : public RefImplementation<MIDIStream>, public MCIDevice { 17 public: create(const char * filename)18 static MCIMIDIStream* create(const char* filename) { 19 // Synchronize on g_song_count? 20 char alias[80]; 21 sprintf(alias, "adr_song_%d", g_song_count); 22 23 bool error; 24 std::string result = sendString( 25 std::string("open \"") + filename + "\" type sequencer alias " + alias, 26 &error); 27 if (error) { 28 return 0; 29 } 30 31 ++g_song_count; 32 return new MCIMIDIStream(alias); 33 } 34 MCIMIDIStream(const std::string & device)35 MCIMIDIStream(const std::string& device) 36 : MCIDevice(device) 37 , m_repeat(false) 38 { 39 sendCommand("set", "time format milliseconds", MCI_WAIT); 40 } 41 play()42 ADR_METHOD(void) play() { 43 if (isPlaying()) { 44 return; 45 } 46 47 if (getPosition() == getLength()) { 48 setPosition(0); 49 } 50 sendCommand("play", "", MCI_NOTIFY); 51 } 52 stop()53 ADR_METHOD(void) stop() { 54 pause(); 55 setPosition(0); 56 } 57 pause()58 ADR_METHOD(void) pause() { 59 sendCommand("stop"); 60 } 61 isPlaying()62 ADR_METHOD(bool) isPlaying() { 63 return sendCommand("status", "mode") == "playing"; 64 } 65 getLength()66 ADR_METHOD(int) getLength() { 67 return atoi(sendCommand("status", "length").c_str()); 68 } 69 getPosition()70 ADR_METHOD(int) getPosition() { 71 int pos = atoi(sendCommand("status", "position").c_str()); 72 int length = getLength(); 73 return (length == 0 ? pos : pos % length); 74 } 75 setPosition(int position)76 ADR_METHOD(void) setPosition(int position) { 77 bool playing = isPlaying(); 78 79 char buffer[80]; 80 sprintf(buffer, "%d", position); 81 sendCommand("seek", std::string("to ") + buffer, MCI_WAIT); 82 83 if (playing) { 84 play(); 85 } 86 } 87 getRepeat()88 ADR_METHOD(bool) getRepeat() { 89 return m_repeat; 90 } 91 setRepeat(bool repeat)92 ADR_METHOD(void) setRepeat(bool repeat) { 93 m_repeat = repeat; 94 } 95 96 protected: notify(WPARAM flags)97 void notify(WPARAM flags) { 98 if (flags == MCI_NOTIFY_SUCCESSFUL) { 99 stop(); 100 if (m_repeat) { 101 play(); 102 } 103 } 104 } 105 106 private: 107 std::string m_device; 108 bool m_repeat; 109 }; 110 111 112 class MCIMIDIDevice : public RefImplementation<MIDIDevice> { 113 public: getName()114 ADR_METHOD(const char*) getName() { 115 return "MCI"; 116 } 117 openStream(const char * filename)118 ADR_METHOD(MIDIStream*) openStream(const char* filename) { 119 return MCIMIDIStream::create(filename); 120 } 121 }; 122 123 124 namespace hidden { 125 AdrOpenMIDIDevice(const char *)126 ADR_EXPORT(MIDIDevice*) AdrOpenMIDIDevice(const char* /*name*/) { 127 return new MCIMIDIDevice; 128 } 129 130 } 131 132 } 133