private string CreateNewSoundFilename(out string path)
        {
            var obj      = m_innerView.Cache.ServiceLocator.GetObject(m_innerView.HvoObj);
            var mediaDir = FdoFileHelper.GetMediaDir(m_innerView.Cache.LangProject.LinkedFilesRootDir);

            Directory.CreateDirectory(mediaDir);             // Palaso media library does not cope if it does not exist.
            // Make up a unique file name for the new recording. It starts with the shortname of the object
            // so as to somewhat link them together, then adds a unique timestamp, then if by any chance
            // that exists it keeps trying.
            var baseNameForFile = obj.ShortName;

            // LT-12926: Path.ChangeExtension checks for invalid filename chars,
            // so we need to fix the filename before calling it.
            foreach (var c in Path.GetInvalidFileNameChars())
            {
                baseNameForFile = baseNameForFile.Replace(c, '_');
            }
            // WeSay and most other programs use NFC for file names, so we'll standardize on this.
            baseNameForFile = baseNameForFile.Normalize(NormalizationForm.FormC);
            string filename;

            do
            {
                filename = baseNameForFile;
                filename = Path.ChangeExtension(DateTime.UtcNow.Ticks + filename, "wav");
                path     = Path.Combine(mediaDir, filename);
            } while (File.Exists(path));
            return(filename);
        }
        private void SetupSoundControls()
        {
            if (m_innerView.WritingSystemsToDisplay == null)
            {
                return;                 // should get called again when it is set up.
            }
            if (m_innerView.RootBox == null)
            {
                return;                 // called again in MakeRoot, when information more complete.
            }
            int index = -1;

            foreach (var ws in m_innerView.WritingSystemsToDisplay)
            {
                index++;
                var pws = ws as WritingSystemDefinition;
                if (pws == null || !pws.IsVoice ||
                    MultiStringSelectionUtils.GetSelAtStartOfWs(m_innerView.RootBox, m_innerView.Flid, index, ws) == null)
                {
                    continue;
                }
                var soundFieldControl = new ShortSoundFieldControl();
                m_soundControls.Add(soundFieldControl);                 // todo: one for each audio one
                soundFieldControl.Visible  = true;
                soundFieldControl.PlayOnly = false;
                var    filename = m_innerView.Cache.DomainDataByFlid.get_MultiStringAlt(m_innerView.HvoObj, m_innerView.Flid, ws.Handle).Text ?? "";
                string path;
                if (String.IsNullOrEmpty(filename))
                {
                    // Provide a filename for copying an existing file to.
                    CreateNewSoundFilename(out path);
                }
                else
                {
                    var mediaDir = FdoFileHelper.GetMediaDir(m_innerView.Cache.LangProject.LinkedFilesRootDir);
                    Directory.CreateDirectory(mediaDir);                     // Palaso media library does not cope if it does not exist.
                    path = Path.Combine(mediaDir, filename.Normalize(NormalizationForm.FormC));

                    // Windows in total defiance of the Unicode standard does not consider alternate normalizations
                    // of file names equal. The name in our string will always be NFD. From 7.2.2 we are saving files
                    // in NFC, but files from older versions could be NFD, so we need to check both. This is not
                    // foolproof...don't know any way to look for all files that might exist with supposedly equivalent
                    // names not normalized at all.
                    if (!File.Exists(path))
                    {
                        var tryPath = path.Normalize(NormalizationForm.FormD);
                        if (File.Exists(tryPath))
                        {
                            path = tryPath;
                        }
                    }
                }
                soundFieldControl.Path = path;
                soundFieldControl.BeforeStartingToRecord += soundFieldControl_BeforeStartingToRecord;
                soundFieldControl.SoundRecorded          += soundFieldControl_SoundRecorded;
                soundFieldControl.SoundDeleted           += soundFieldControl_SoundDeleted;
                Controls.Add(soundFieldControl);
            }
        }