/// ------------------------------------------------------------------------------------
        /// <summary>
        /// Copies the transcription data from one audio document to another.
        /// </summary>
        /// ------------------------------------------------------------------------------------
        public void Copy(string destFilePath, bool md5MustMatch)
        {
            // first check MD5
            if (md5MustMatch && (AudioReader.GetMD5HashCode(destFilePath) != m_doc.MD5HashCode))
            {
                return;
            }

            // copy the transcription data
            m_doc           = m_doc.Clone();
            m_doc.AudioFile = destFilePath;
            Commit();
        }
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Initializes an object to read SA data from the SA database.
        /// </summary>
        /// ------------------------------------------------------------------------------------
        public bool Initialize(string audioFilePath, bool isForTmpOperation)
        {
            // Check if the DB used in some beta versions still exists. If so,
            // then convert the documents therein to companion transcription files.
            ConvertOldDatabaseToCompanionFiles();

            m_doc = SaAudioDocument.Load(audioFilePath, isForTmpOperation, true);
            if (m_doc != null)
            {
                ResetSegmentEnumerators();
                return(true);
            }

            try {
                using (AudioReader audioReader = new AudioReader()) {
                    AudioReader.InitResult result = audioReader.Initialize(audioFilePath);
                    if (result == AudioReader.InitResult.FileNotFound)
                    {
                        string msg = string.Format(Resources.kstidWaveFileNotFound, GUI.Utils.PrepFilePathForMsgBox(audioFilePath));
                        GUI.Utils.MsgBox(msg, MessageBoxButtons.OK);
                        return(false);
                    }

                    if ((result == AudioReader.InitResult.InvalidFormat))
                    {
                        string msg = string.Format(Resources.kstidInvalidWaveFile, GUI.Utils.PrepFilePathForMsgBox(audioFilePath));
                        GUI.Utils.MsgBox(msg, MessageBoxButtons.OK);
                        return(false);
                    }

                    // Try reading data from older SA audio files, converting
                    // it to Unicode along the way.
                    if (!audioReader.Read())
                    {
                        return(false);
                    }

                    // Now try reading the companion transcription file again.
                    m_doc = SaAudioDocument.Load(audioFilePath, isForTmpOperation, false);
                    ResetSegmentEnumerators();
                }
            } catch (Exception e) {
                string msg = string.Format(Resources.kstidErrorInitializingDocReader, e.Message);
                GUI.Utils.MsgBox(msg, MessageBoxButtons.OK);
                return(false);
            }

            return(true);
        }
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Commits to a transcription file the data collected in SaAudioDocumentWriter.
        /// When backupOldAudioFile is true, the assumption is the audio file contains
        /// old SA chunks and they are stripped out after the file is backed up.
        /// </summary>
        /// ------------------------------------------------------------------------------------
        public bool Commit(bool backupOldAudioFile)
        {
            bool retVal = m_doc.Save();

            if (!retVal)
            {
                return(false);
            }

            if (backupOldAudioFile)
            {
                // First, make a backup copy of the file.
                string newExt  = "SA2" + Path.GetExtension(m_doc.AudioFile);
                string newPath = Path.GetDirectoryName(m_doc.AudioFile);
                if (!newPath.EndsWith("\\"))
                {
                    newPath += "\\";
                }
                newPath += "SA2 Wav Files\\";
                Directory.CreateDirectory(newPath);
                newPath += Path.GetFileName(m_doc.AudioFile);
                newPath  = Path.ChangeExtension(newPath, newExt);

                if (!File.Exists(newPath))  // don't copy if it's already backed up
                {
                    File.Copy(m_doc.AudioFile, newPath);
                }
            }

            if ((File.GetAttributes(m_doc.AudioFile) & FileAttributes.ReadOnly) != FileAttributes.ReadOnly)
            {
                File.SetAttributes(m_doc.AudioFile, FileAttributes.Normal);

                int    newFileLength;
                byte[] bytes = null;

                // Now, read all the bytes in the file that are not from SA chunks.
                using (FileStream stream = File.Open(m_doc.AudioFile, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)) {
                    // Get the offset in the file of the first SA chunk. That will
                    // be the length of the file after the SA chunks are removed.
                    newFileLength = (int)AudioReader.GetChunkOffset(stream, AudioReader.kidSAChunk);
                    if (newFileLength > 0)
                    {
                        stream.Position = 0;
                        BinaryReader reader = new BinaryReader(stream);
                        bytes = reader.ReadBytes(newFileLength);
                    }

                    stream.Flush();
                    stream.Close();
                }

                if (newFileLength <= 0 || bytes == null)
                {
                    return(true);
                }

                // Now rewrite the file without all the SA chunks. Write all the bytes
                // then skip over the 'RIFF' tag and write out the modify RIFF chunk
                // length, which is 8 bytes less than the length of the file since it
                // doesn't include 'RIFF' and the 4 bytes for the RIFF chunk length.
                using (FileStream stream = File.Open(m_doc.AudioFile, FileMode.Truncate, FileAccess.Write, FileShare.ReadWrite)) {
                    BinaryWriter writer = new BinaryWriter(stream);
                    writer.Write(bytes);
                    stream.Position = 4;
                    writer.Write(newFileLength - 8);
                    stream.Close();
                }
            }
            return(true);
        }