Exemple #1
0
        //バイナリからデータを上書き・追加
        public void Read(BinaryReader reader)
        {
            int magicID = reader.ReadInt32();

            if (magicID != MagicID)
            {
                throw new System.Exception("Read File Error " + magicID);
            }

            FileLists.Clear();
            int version = reader.ReadInt32();

            if (version == Version)
            {
                int count = reader.ReadInt32();
                for (int i = 0; i < count; ++i)
                {
                    string key = reader.ReadString();
                    ConvertFileInfoDictionary assetBundleDictionary = new ConvertFileInfoDictionary(this, key);
                    assetBundleDictionary.Read(reader);
                    FileLists.Add(assetBundleDictionary.Key, assetBundleDictionary);
                }
            }
            else
            {
                throw new System.Exception(LanguageErrorMsg.LocalizeTextFormat(ErrorMsg.UnknownVersion, version));
            }
        }
Exemple #2
0
        //独自定義ファイルをバージョンアップする。バージョンアップチェックはしない(Eidtor上のみ使用可能)
        public void EditorVersionUp(string key, List <CusomFileVersionUpInfo> cusomFileVersionUpInfoList)
        {
            ConvertFileInfoDictionary oldInfoList;

            FileLists.TryGetValue(key, out oldInfoList);
            ConvertFileInfoDictionary newInfoList = new ConvertFileInfoDictionary(this, key);

            foreach (var versionUpInfo in cusomFileVersionUpInfoList)
            {
                ConvertFileInfo info;
                if (oldInfoList != null && oldInfoList.TryGetValue(versionUpInfo.Name, out info))
                {
                    if (versionUpInfo.IsVersionUp)
                    {
                        info.VersionUp();
                    }
                }
                else
                {
                    info = new ConvertFileInfo(versionUpInfo.Name, newInfoList);
                }
                if (newInfoList.ContainsKey(info.Name))
                {
                    Debug.LogError(info.Name + " is already contains ");
                    continue;
                }
                newInfoList.Add(info.Name, info);
            }
            FileLists.Remove(key);
            FileLists.Add(key, newInfoList);
        }
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            var parameters = e.Parameter as Procedure_FileLists;

            myOptions = parameters.procedure.myOptions;

            string tmp = null;

            foreach (var i in myOptions)
            {
                if (i.Substring(3) == "5")
                {
                    (FindName("option" + i.Substring(3) + "fc") as TextBox).IsEnabled = true;
                    tmp = i;
                }
                else if (i.Substring(3) != "2")
                {
                    (FindName("option" + i.Substring(3) + "f") as TextBox).IsEnabled = true;
                    (FindName("option" + i.Substring(3) + "t") as TextBox).IsEnabled = true;
                }
                else if (i.Substring(3) == "2")
                {
                    (FindName("option" + i.Substring(3) + "fo") as Button).IsEnabled = true;
                }
            }
            fileLists = parameters.fileLists;

            if (tmp != null)
            {
                myOptions.Remove(tmp);
            }
        }
Exemple #4
0
        //データをバージョンアップする(Eidtor上のみ使用可能)
        public int EditorVersionUpAssetBundle(AssetBundleManifest manifest, UnityEditor.BuildTarget buildTarget)
        {
            int    count          = 0;
            string buildTargetKey = AssetBundleHelper.BuildTargetToBuildTargetFlag(buildTarget).ToString();
            ConvertFileInfoDictionary oldInfoList;

            FileLists.TryGetValue(buildTargetKey, out oldInfoList);

            ConvertFileInfoDictionary newInfoList = new ConvertFileInfoDictionary(this, buildTargetKey);

            foreach (string assetBundleName in manifest.GetAllAssetBundles())
            {
                ConvertFileInfo info;
                if (oldInfoList != null && oldInfoList.TryGetValue(assetBundleName, out info))
                {
                    if (info.VersionUp(manifest))
                    {
                        ++count;
                    }
                }
                else
                {
                    info = new ConvertFileInfo(assetBundleName, manifest, newInfoList);
                    ++count;
                }
                newInfoList.Add(info.Name, info);
            }
            FileLists.Remove(newInfoList.Key);
            FileLists.Add(newInfoList.Key, newInfoList);
            return(count);
        }
Exemple #5
0
        public async Task <IActionResult> GetFileList(string directory)
        {
            directory = HttpUtility.UrlDecode(directory);

            string resolvedPath = "n/a";

            try
            {
                resolvedPath = await ResolvePath(directory);

                if (!Directory.Exists(resolvedPath))
                {
                    _logger.LogWarning($"[{nameof(GetFileList)}] Could not find directory {directory} (resolved to {resolvedPath})");
                    return(NotFound(HttpUtility.UrlPathEncode(directory)));
                }
                return(Content(FileLists.GetFileList(directory, resolvedPath), "application/json"));
            }
            catch (AggregateException ae) when(ae.InnerException is IncompatibleVersionException)
            {
                _logger.LogError($"[{nameof(GetFileList)}] Incompatible DCS version");
                return(StatusCode(502, ae.InnerException.Message));
            }
            catch (AggregateException ae) when(ae.InnerException is SocketException)
            {
                _logger.LogError($"[{nameof(GetFileList)}] DCS is unavailable");
                return(StatusCode(503, ae.InnerException.Message));
            }
            catch (Exception e)
            {
                _logger.LogWarning(e, $"[{nameof(GetFileList)}] Failed to retrieve file list for {directory} (resolved to {resolvedPath})");
                return(StatusCode(500, e.Message));
            }
        }
        public MainPage()
        {
            CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = false;
            ApplicationView.GetForCurrentView().TitleBar.ButtonBackgroundColor = Colors.Transparent;
            this.InitializeComponent();

            myRandomizer      = new Randomizer();
            uploadedFileLists = new FileLists();
        }
        public DnSpyFileListManager(IDnSpyFileListOptions options, DNSpySettings spySettings)
        {
            this.options = options;
            var doc = GetFileListsElement(spySettings);

            foreach (var list in doc.Elements(LIST_SECTION_NAME))
            {
                FileLists.Add(SessionSettings.Unescape((string)list.Attribute("name")));
            }
        }
Exemple #8
0
        internal static async Task StartProcessing()
        {
            if (GetResizeAndOptimize.StartButton.Content.ToString() == "Stop")
            {
                cts.Cancel();
                HandleCencalled();
                return;
            }

            string file = Pics[FolderIndex];

            GetResizeAndOptimize.UIprogressbar.Value = 0;

            GatherData();

            if (!GetResizeAndOptimize.AllRadio.IsChecked.Value)
            {
                await Task.Run(() =>
                               ImageDecoder.TransformImage(file, resize, width, height, aspectRatio, rotation, quality,
                                                           optimize, flip, name, destinationFolder)).ConfigureAwait(false);

                return;
            }

            GetResizeAndOptimize.StartButton.Content = "Stop";

            var progress = new Progress <string>();

            progress.ProgressChanged += Progress_ProgressChanged;

            var currentFolder = Path.GetDirectoryName(Pics[FolderIndex]);

            if (currentFolder != sourceFolder)
            {
                var tempFileList = FileLists.FileList(sourceFolder);
                GetResizeAndOptimize.UIprogressbar.Maximum = tempFileList.Count;
                try
                {
                    await TransformImagesAsync(tempFileList, progress, resize, width, height, aspectRatio, rotation, quality,
                                               optimize, flip, name, destinationFolder, cts.Token).ConfigureAwait(false);
                }
                catch (OperationCanceledException) { return; }
            }
            else
            {
                GetResizeAndOptimize.UIprogressbar.Maximum = Pics.Count;

                await TransformImagesAsync(Pics, progress, resize, width, height, aspectRatio, rotation, quality,
                                           optimize, flip, name, destinationFolder, cts.Token).ConfigureAwait(false);
            }
        }
Exemple #9
0
        private static void AddMusicFile(int No, string path)
        {
            FileMusic fMusic = new FileMusic(path);

            fMusic.No = No;
            if (CutParenthesisTitle)
            {
                fMusic.CutParenthesis(CutParenthesisItem.Title);
            }
            if (CutParenthesisArtist)
            {
                fMusic.CutParenthesis(CutParenthesisItem.Artist);
            }

            FileLists.Add(fMusic);
        }
Exemple #10
0
        public static void CreateListByExtenstion(string path)
        {
            int i = 0;

            if (Directory.Exists(path))
            {
                if (FileLists == null)
                {
                    FileLists = new List <FileClass>();
                }
                else
                {
                    FileLists.Clear();
                }

                foreach (string fileName in Directory.GetFiles(path, "*.MP3"))
                {
                    AddMusicFile(++i, fileName);
                }
            }
        }
Exemple #11
0
        //ファイルのパスから、ファイル情報を取得
        public bool TryGetValue(string filePath, AssetFileEncodeType encodeType, out ConvertFileInfo info)
        {
            info = null;
            switch (encodeType)
            {
            case AssetFileEncodeType.AlreadyEncoded:
                if (!FilePathUtil.IsUnderDirectory(filePath, DirectoryPath))
                {
                    return(false);
                }
                string fileKey = FilePathUtil.RemoveDirectory(filePath, DirectoryPath);
                foreach (var files in FileLists.Values)
                {
                    if (files.TryGetValue(fileKey, out info))
                    {
                        return(true);
                    }
                }
                return(false);

            case AssetFileEncodeType.AssetBundle:
                string assetName   = FilePathUtil.GetFileNameWithoutExtension(filePath).ToLower();
                string keyPlatform = AssetBundleHelper.RuntimeAssetBundleTraget().ToString();
                ConvertFileInfoDictionary infoList;
                if (FileLists.TryGetValue(keyPlatform, out infoList))
                {
                    if (infoList.TryGetValue(assetName, out info))
                    {
                        return(true);
                    }
                }
                return(false);

            default:
                return(false);
            }
        }
Exemple #12
0
        public static bool ConvertFileNameAt(int index)
        {
            string    newFileName = string.Empty;
            FileMusic muFile      = (FileMusic)FileLists.ElementAt(index);

            if (string.IsNullOrEmpty(muFile.Artist) && string.IsNullOrEmpty(muFile.Title))
            {
                newFileName = muFile.FileName;
            }
            else
            {
                newFileName = string.Concat("[", muFile.Artist, "]", muFile.Title, ".mp3");
            }

            if (SavePath.Equals(string.Empty))
            {
                return(false);
            }

            if (!Directory.Exists(@SavePath))
            {
                Directory.CreateDirectory(@SavePath);
            }

            try
            {
                var sourceFile = string.Concat(FileLists.ElementAt(index).FilePath, "\\", FileLists.ElementAt(index).FileName);

                File.Copy(sourceFile, string.Concat(@SavePath, "//", newFileName), true);
                File.Delete(sourceFile);
            }
            catch (Exception ex)
            {
            }

            return(true);
        }
Exemple #13
0
        private static void AdaptElementPaths(Dictionary <String, String> filesMoved, String musicDir, String soundsDir, IProject project)
        {
            if (project == null)
            {
                return;
            }

            FileLists            lists    = new FileLists();
            IList <IFileElement> elements = lists.GetAllFiles(project);

            foreach (IFileElement element in elements)
            {
                String basePath    = element.SoundFileType == SoundFileType.Music ? musicDir : soundsDir;
                String currentPath = System.IO.Path.Combine(basePath, element.FilePath);
                if (filesMoved.ContainsKey(currentPath))
                {
                    String newPath = filesMoved[currentPath];
                    if (newPath.StartsWith(basePath, StringComparison.InvariantCultureIgnoreCase))
                    {
                        element.FilePath = newPath.Substring(basePath.Length + 1);
                    }
                }
            }
        }
        public async Task <bool> DoJob(FileLists uploadedFileLists, StorageFile another_file)
        {
            FileLists beforeLists = new FileLists();
            FileLists afterLists  = new FileLists();

            await new MessageDialog("결과 파일을 저장할 대상 폴더를 지정해주세요.")
            {
                Title = "폴더선택"
            }.ShowAsync();

            var picker = new FolderPicker();

            picker.SuggestedStartLocation = PickerLocationId.Desktop;
            picker.FileTypeFilter.Add("*");

            StorageFolder folder = await picker.PickSingleFolderAsync();


            if (folder == null)
            {
                return(true);
            }

            int mycnt = 1;

            while (job.Count != 0)
            {
                int now = job.Dequeue();

                int  k = 1;
                bool doRandom = true;
                int  from = 0, to = 0;
                if (now == 1)
                {
                    from = int.Parse(option1f);
                    to   = int.Parse(option1t);
                }
                else if (now == 2)
                {
                }
                else if (now == 3)
                {
                    from = int.Parse(option3f);
                    to   = int.Parse(option3t);
                }
                else if (now == 4)
                {
                    from = int.Parse(option4f);
                    to   = int.Parse(option4t);
                }
                else if (now == 5)
                {
                    from = int.Parse(option5fc);
                }

                ProgressBar progressBar = new ProgressBar();
                progressBar.IsIndeterminate = true;

                ContentDialog progress_dialog = new ContentDialog()
                {
                    Content = progressBar,
                    Title   = "옵션" + now.ToString() + " 작업중입니다"
                };
#pragma warning disable CS4014 // 이 호출을 대기하지 않으므로 호출이 완료되기 전에 현재 메서드가 계속 실행됩니다.
                progress_dialog.ShowAsync();
#pragma warning restore CS4014 // 이 호출을 대기하지 않으므로 호출이 완료되기 전에 현재 메서드가 계속 실행됩니다.

                if (now == 5)
                {
                    List <UploadedFile> items = new List <UploadedFile>();
                    if (mycnt == 1)
                    {
                        foreach (var i in uploadedFileLists)
                        {
                            items.Add(i);
                        }
                    }
                    else
                    {
                        foreach (var i in afterLists)
                        {
                            items.Add(i);
                        }
                    }

                    int idx = 0;

                    int sz = items.Count / from + ((items.Count % from > 0)? 1 : 0);
                    for (int T = 1; T <= sz; T++)
                    {
                        StorageFile tmp_f = await folder.CreateFileAsync(T.ToString() + ".zip", CreationCollisionOption.ReplaceExisting);

                        using (Stream s = await tmp_f.OpenStreamForWriteAsync())
                        {
                            using (ZipArchive zz = new ZipArchive(s, ZipArchiveMode.Update))
                            {
                                for (int i = 0; i < from; i++)
                                {
                                    if (i + idx < items.Count)
                                    {
                                        ZipArchiveEntry read;
                                        if (mycnt == 1)
                                        {
                                            read = zz.CreateEntry(items[i + idx].inputName);
                                        }
                                        else
                                        {
                                            read = zz.CreateEntry(items[i + idx].outputName);
                                        }

                                        using (StreamWriter sw = new StreamWriter(read.Open()))
                                        {
                                            Stream ss;
                                            if (mycnt == 1)
                                            {
                                                ss = await items[i + idx].originFile.OpenStreamForReadAsync();
                                            }
                                            else
                                            {
                                                ss = await items[i + idx].outputFile.OpenStreamForReadAsync();
                                            }
                                            {
                                                using (StreamReader sr = new StreamReader(ss))
                                                {
                                                    string tmp;
                                                    while ((tmp = await sr.ReadLineAsync()) != null)
                                                    {
                                                        await sw.WriteLineAsync(tmp);
                                                    }
                                                }
                                            }
                                            ss.Close();
                                        }
                                    }
                                }
                            }
                        }
                        idx += from;
                    }

                    if (mycnt != 1)
                    {
                        foreach (var i in items)
                        {
                            await i.outputFile.DeleteAsync(StorageDeleteOption.PermanentDelete);
                        }
                    }
                }
                else
                {
                    if (mycnt == 1)
                    {
                        afterLists = await myRandomizer.DoRandom(uploadedFileLists, folder, another_file, k, doRandom, from, to, Q, now);
                    }
                    else
                    {
                        foreach (var i in afterLists)
                        {
                            i.originFile = i.outputFile;
                        }
                        beforeLists = afterLists;
                        afterLists  = await myRandomizer.DoRandom(beforeLists, folder, another_file, k, doRandom, from, to, Q, now);

                        foreach (var i in beforeLists)
                        {
                            try
                            {
                                await i.originFile.DeleteAsync(StorageDeleteOption.PermanentDelete);
                            }
                            catch { }
                        }
                    }
                    mycnt++;
                    while (Q.Count != 0)
                    {
                        Tuple <StorageFile, string> fff = Q.Dequeue();

                        try
                        {
                            await FileIO.WriteTextAsync(fff.Item1, fff.Item2);
                        }
                        catch
                        {
                            Q.Enqueue(fff);
                        }
                    }
                }
                progress_dialog.Hide();
            }

            return(false);
        }
 public TaskPlannerMirror(UserInterface.UserInterfaceBase userOptions, TaskViews taskSource, TaskViews taskTarget, Tasks.Tasks tasks, FileLists fileLists, PlaylistUpdates.PlaylistUpdates playlistUpdates)
     : base(userOptions, taskSource, taskTarget, tasks, fileLists, playlistUpdates)
 {
     //
 }
Exemple #16
0
        public async Task <FileLists> DoRandom(FileLists fl, StorageFolder folder, StorageFile another_file, int k, bool doRandom, int from, int to, Queue <Tuple <StorageFile, string> > Q, int option)
        {
            FileLists retLists = new FileLists();

            Random random = new Random(DateTime.Now.Millisecond);

            if (option == 1)
            {
                foreach (UploadedFile i in fl)
                {
                    await i.setOutFile(folder); // wait until setOutFile ends

                    // read stream from storagefile
                    using (Stream s = await i.originFile.OpenStreamForReadAsync())
                    {
                        // streamreader from stream
                        using (StreamReader sr = new StreamReader(s))
                        {
                            string str = await sr.ReadToEndAsync();

                            StringBuilder stringBuilder = new StringBuilder(str);
                            List <string> ans           = new List <string>();
                            if (doRandom)
                            {
                                ans = doOption1(stringBuilder, random.Next(from, to + 1));
                            }
                            else
                            {
                                ans = doOption1(stringBuilder, k);
                            }
                            StringBuilder ret = new StringBuilder();
                            foreach (var j in ans)
                            {
                                ret.Append(j);
                            }

                            retLists.Add(i);
                            try
                            {
                                await FileIO.WriteTextAsync(i.outputFile, ret.ToString());
                            }
                            catch
                            {
                                Q.Enqueue(new Tuple <StorageFile, string>(i.outputFile, ret.ToString()));
                            }
                        }
                    }
                }
            }
            else if (option == 2) //옵션2
            {
                if (another_file.IsAvailable)
                {
                    using (Stream another_s = await another_file.OpenStreamForReadAsync())
                    {
                        using (StreamReader another_sr = new StreamReader(another_s))
                        {
                            foreach (UploadedFile i in fl)
                            {
                                string readed = await another_sr.ReadLineAsync();

                                if (readed == null)
                                {
                                    break;
                                }
                                await i.setOutFile(folder);

                                using (Stream s = await i.originFile.OpenStreamForReadAsync())
                                {
                                    using (StreamReader sr = new StreamReader(s))
                                    {
                                        string appending = await sr.ReadToEndAsync();

                                        string appended = readed + Environment.NewLine + appending;

                                        retLists.Add(i);
                                        try
                                        {
                                            await FileIO.WriteTextAsync(i.outputFile, appended);
                                        }
                                        catch
                                        {
                                            Q.Enqueue(new Tuple <StorageFile, string>(i.outputFile, appended));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else if (option == 3)
            {
                foreach (UploadedFile file in fl)
                {
                    using (Stream s = await file.originFile.OpenStreamForReadAsync())
                    {
                        using (StreamReader sr = new StreamReader(s))
                        {
                            bool chk = true;
                            while (true)
                            {
                                List <string> vs = new List <string>();
                                if (doRandom)
                                {
                                    k = random.Next(from, to + 1);
                                }
                                for (int i = 0; i < k; i++)
                                {
                                    string tmp = await sr.ReadLineAsync();

                                    if (tmp == "")
                                    {
                                        continue;
                                    }
                                    else if (tmp == null)
                                    {
                                        chk = false;
                                        break;
                                    }
                                    vs.Add(tmp);
                                }
                                StringBuilder newTextsb = new StringBuilder();

                                foreach (var i in vs)
                                {
                                    newTextsb.Append(i);
                                    newTextsb.Append(Environment.NewLine);
                                }

                                await file.setOutFile(folder);

                                UploadedFile ref_file = file.Clone() as UploadedFile;

                                retLists.Add(ref_file);
                                try
                                {
                                    await FileIO.WriteTextAsync(file.outputFile, newTextsb.ToString());
                                }
                                catch
                                {
                                    Q.Enqueue(new Tuple <StorageFile, string>(file.outputFile, newTextsb.ToString()));
                                }
                                if (!chk)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            else if (option == 4)
            {
                foreach (var i in fl)
                {
                    List <string> sL = new List <string>();
                    using (Stream s = await i.originFile.OpenStreamForReadAsync())
                    {
                        using (StreamReader sr = new StreamReader(s))
                        {
                            string tmp;
                            while ((tmp = await sr.ReadLineAsync()) != null)
                            {
                                sL.Add(tmp);
                            }
                        }
                    }

                    await i.setOutFile(folder);

                    retLists.Add(i);

                    if (doRandom)
                    {
                        k = random.Next(from, to + 1);
                    }


                    for (int t = 0; t < 3; t++)
                    {
                        int tmp_cnt = k;
                        for (int j = 0; j < tmp_cnt; j++)
                        {
                            int now;
                            if (sL.Count == 0)
                            {
                                break;
                            }
                            now = random.Next(0, sL.Count);

                            if (sL[now] == "")
                            {
                                continue;
                            }
                            if (now - 1 >= 0 && sL[now - 1] == "")
                            {
                                continue;
                            }
                            if (now + 1 < sL.Count && sL[now + 1] == "")
                            {
                                continue;
                            }

                            sL.Insert(now, "");
                            k--;
                        }
                    }

                    if (k > 0)
                    {
                        for (int j = 0; j < sL.Count; j++)
                        {
                            if (sL[j] == "")
                            {
                                continue;
                            }
                            if (j - 1 >= 0 && sL[j - 1] == "")
                            {
                                continue;
                            }
                            if (j + 1 < sL.Count && sL[j + 1] == "")
                            {
                                continue;
                            }
                            sL.Insert(j, "");
                            k--;
                            if (k == 0)
                            {
                                break;
                            }
                        }
                    }

                    StringBuilder str = new StringBuilder();

                    for (int j = 0; j < sL.Count; j++)
                    {
                        str.Append(sL[j]);
                        str.Append(Environment.NewLine);
                    }

                    try
                    {
                        await FileIO.WriteTextAsync(i.outputFile, str.ToString());
                    }
                    catch
                    {
                        Q.Enqueue(new Tuple <StorageFile, string>(i.outputFile, str.ToString()));
                    }
                }
            }

            /* deprecated another option,
             * else if(option==5)
             * {
             *  int cnt = 0;
             *  StringBuilder sb = new StringBuilder();
             *  foreach(UploadedFile file in fl)
             *  {
             *      cnt++;
             *      using (Stream s = await file.originFile.OpenStreamForReadAsync())
             *      {
             *          using (StreamReader sr = new StreamReader(s))
             *          {
             *              string str;
             *              while( (str = await sr.ReadLineAsync()) != null)
             *              {
             *                  sb.Append(str);
             *                  sb.Append(Environment.NewLine);
             *              }
             *              if (cnt == from)
             *              {
             *                  await file.setOutFile(folder);
             *                  try
             *                  {
             *                      await FileIO.WriteTextAsync(file.outputFile, sb.ToString());
             *                  }
             *                  catch
             *                  {
             *                      Q.Enqueue(new Tuple<StorageFile, string>(file.outputFile, sb.ToString()));
             *                  }
             *                  cnt = 0;
             *                  sb.Clear();
             *              }
             *          }
             *      }
             *  }
             *  if (sb.Length>0)
             *  {
             *
             *      await fl[0].setOutFile(folder);
             *      try
             *      {
             *          await FileIO.WriteTextAsync(fl[0].outputFile, fl[0].ToString());
             *      }
             *      catch
             *      {
             *          Q.Enqueue(new Tuple<StorageFile, string>(fl[0].outputFile, sb.ToString()));
             *      }
             *      sb.Clear();
             *  }
             * }
             */

            return(retLists);
        }
Exemple #17
0
        /// <summary>
        /// Process an M-code that should be interpreted by the control server
        /// </summary>
        /// <param name="code">Code to process</param>
        /// <returns>Result of the code if the code completed, else null</returns>
        public static async Task <CodeResult> Process(Commands.Code code)
        {
            if (code.Channel == CodeChannel.File && FileExecution.Job.IsSimulating)
            {
                // Ignore M-codes from files in simulation mode...
                return(null);
            }

            switch (code.MajorNumber)
            {
            // Stop or Unconditional stop
            // Sleep or Conditional stop
            case 0:
            case 1:
                if (await SPI.Interface.Flush(code))
                {
                    using (await FileExecution.Job.LockAsync())
                    {
                        if (FileExecution.Job.IsFileSelected)
                        {
                            // M0/M1 may be used in a print file to terminate it
                            if (code.Channel != CodeChannel.File && !FileExecution.Job.IsPaused)
                            {
                                return(new CodeResult(MessageType.Error, "Pause the print before attempting to cancel it"));
                            }
                        }
                    }
                    break;
                }
                throw new OperationCanceledException();

            // List SD card
            case 20:
                if (await SPI.Interface.Flush(code))
                {
                    // Resolve the directory
                    string virtualDirectory = code.Parameter('P');
                    if (virtualDirectory == null)
                    {
                        using (await Model.Provider.AccessReadOnlyAsync())
                        {
                            virtualDirectory = Model.Provider.Get.Directories.GCodes;
                        }
                    }
                    string physicalDirectory = await FilePath.ToPhysicalAsync(virtualDirectory);

                    // Make sure to stay within limits if it is a request from the firmware
                    int maxSize = -1;
                    if (code.Flags.HasFlag(CodeFlags.IsFromFirmware))
                    {
                        maxSize = Settings.MaxMessageLength;
                    }

                    // Check if JSON file lists were requested
                    int           startAt = Math.Max(code.Parameter('R') ?? 0, 0);
                    CodeParameter sParam  = code.Parameter('S', 0);
                    if (sParam == 2)
                    {
                        string json = FileLists.GetFiles(virtualDirectory, physicalDirectory, startAt, true, maxSize);
                        return(new CodeResult(MessageType.Success, json));
                    }
                    if (sParam == 3)
                    {
                        string json = FileLists.GetFileList(virtualDirectory, physicalDirectory, startAt, maxSize);
                        return(new CodeResult(MessageType.Success, json));
                    }

                    // Print standard G-code response
                    Compatibility compatibility;
                    using (await Model.Provider.AccessReadOnlyAsync())
                    {
                        compatibility = Model.Provider.Get.Inputs[code.Channel].Compatibility;
                    }

                    StringBuilder result = new StringBuilder();
                    if (compatibility == Compatibility.Default || compatibility == Compatibility.RepRapFirmware)
                    {
                        result.AppendLine("GCode files:");
                    }
                    else if (compatibility == Compatibility.Marlin || compatibility == Compatibility.NanoDLP)
                    {
                        result.AppendLine("Begin file list:");
                    }

                    int  numItems  = 0;
                    bool itemFound = false;
                    foreach (string file in Directory.EnumerateFileSystemEntries(physicalDirectory))
                    {
                        if (numItems++ >= startAt)
                        {
                            string filename = Path.GetFileName(file);
                            if (compatibility == Compatibility.Marlin || compatibility == Compatibility.NanoDLP)
                            {
                                result.AppendLine(filename);
                            }
                            else
                            {
                                if (itemFound)
                                {
                                    result.Append(',');
                                }
                                result.Append($"\"{filename}\"");
                            }
                            itemFound = true;
                        }
                    }

                    if (compatibility == Compatibility.Marlin || compatibility == Compatibility.NanoDLP)
                    {
                        if (!itemFound)
                        {
                            result.AppendLine("NONE");
                        }
                        result.Append("End file list");
                    }

                    return(new CodeResult(MessageType.Success, result.ToString()));
                }
                throw new OperationCanceledException();

            // Initialize SD card
            case 21:
                if (await SPI.Interface.Flush(code))
                {
                    if (code.Parameter('P', 0) == 0)
                    {
                        // M21 (P0) will always work because it's always mounted
                        return(new CodeResult());
                    }
                    throw new NotSupportedException();
                }
                throw new OperationCanceledException();

            // Release SD card
            case 22:
                throw new NotSupportedException();

            // Select a file to print
            case 23:
            case 32:
                if (await SPI.Interface.Flush(code))
                {
                    string file = code.GetUnprecedentedString();
                    if (string.IsNullOrWhiteSpace(file))
                    {
                        return(new CodeResult(MessageType.Error, "Filename expected"));
                    }

                    string physicalFile = await FilePath.ToPhysicalAsync(file, FileDirectory.GCodes);

                    if (!File.Exists(physicalFile))
                    {
                        return(new CodeResult(MessageType.Error, $"Could not find file {file}"));
                    }

                    using (await FileExecution.Job.LockAsync())
                    {
                        if (code.Channel != CodeChannel.File && FileExecution.Job.IsProcessing)
                        {
                            return(new CodeResult(MessageType.Error, "Cannot set file to print, because a file is already being printed"));
                        }
                        await FileExecution.Job.SelectFile(physicalFile);
                    }

                    if (await code.EmulatingMarlin())
                    {
                        return(new CodeResult(MessageType.Success, "File opened\nFile selected"));
                    }
                    return(new CodeResult(MessageType.Success, $"File {file} selected for printing"));
                }
                throw new OperationCanceledException();


            // Resume a file print
            case 24:
                if (await SPI.Interface.Flush(code))
                {
                    using (await FileExecution.Job.LockAsync())
                    {
                        if (!FileExecution.Job.IsFileSelected)
                        {
                            return(new CodeResult(MessageType.Error, "Cannot print, because no file is selected!"));
                        }
                    }

                    // Let RepRapFirmware process this request so it can invoke resume.g. When M24 completes, the file is resumed
                    break;
                }
                throw new OperationCanceledException();

            // Set SD position
            case 26:
                if (await SPI.Interface.Flush(code))
                {
                    using (await FileExecution.Job.LockAsync())
                    {
                        if (!FileExecution.Job.IsFileSelected)
                        {
                            return(new CodeResult(MessageType.Error, "Not printing a file"));
                        }

                        CodeParameter sParam = code.Parameter('S');
                        if (sParam != null)
                        {
                            if (sParam < 0L || sParam > FileExecution.Job.FileLength)
                            {
                                return(new CodeResult(MessageType.Error, "Position is out of range"));
                            }
                            await FileExecution.Job.SetFilePosition(sParam);
                        }
                    }

                    // P is not supported yet

                    return(new CodeResult());
                }
                throw new OperationCanceledException();

            // Report SD print status
            case 27:
                if (await SPI.Interface.Flush(code))
                {
                    using (await FileExecution.Job.LockAsync())
                    {
                        if (FileExecution.Job.IsFileSelected)
                        {
                            long filePosition = await FileExecution.Job.GetFilePosition();

                            return(new CodeResult(MessageType.Success, $"SD printing byte {filePosition}/{FileExecution.Job.FileLength}"));
                        }
                        return(new CodeResult(MessageType.Success, "Not SD printing."));
                    }
                }
                throw new OperationCanceledException();

            // Begin write to SD card
            case 28:
                if (await SPI.Interface.Flush(code))
                {
                    int numChannel = (int)code.Channel;
                    using (await Commands.Code.FileLocks[numChannel].LockAsync(Program.CancellationToken))
                    {
                        if (Commands.Code.FilesBeingWritten[numChannel] != null)
                        {
                            return(new CodeResult(MessageType.Error, "Another file is already being written to"));
                        }

                        string file = code.GetUnprecedentedString();
                        if (string.IsNullOrWhiteSpace(file))
                        {
                            return(new CodeResult(MessageType.Error, "Filename expected"));
                        }

                        string prefix       = (await code.EmulatingMarlin()) ? "ok\n" : string.Empty;
                        string physicalFile = await FilePath.ToPhysicalAsync(file, FileDirectory.GCodes);

                        try
                        {
                            FileStream   fileStream = new FileStream(physicalFile, FileMode.Create, FileAccess.Write);
                            StreamWriter writer     = new StreamWriter(fileStream);
                            Commands.Code.FilesBeingWritten[numChannel] = writer;
                            return(new CodeResult(MessageType.Success, prefix + $"Writing to file: {file}"));
                        }
                        catch (Exception e)
                        {
                            _logger.Debug(e, "Failed to open file for writing");
                            return(new CodeResult(MessageType.Error, prefix + $"Can't open file {file} for writing."));
                        }
                    }
                }
                throw new OperationCanceledException();

            // End write to SD card
            case 29:
                if (await SPI.Interface.Flush(code))
                {
                    int numChannel = (int)code.Channel;
                    using (await Commands.Code.FileLocks[numChannel].LockAsync(Program.CancellationToken))
                    {
                        if (Commands.Code.FilesBeingWritten[numChannel] != null)
                        {
                            Stream stream = Commands.Code.FilesBeingWritten[numChannel].BaseStream;
                            Commands.Code.FilesBeingWritten[numChannel].Dispose();
                            Commands.Code.FilesBeingWritten[numChannel] = null;
                            stream.Dispose();

                            if (await code.EmulatingMarlin())
                            {
                                return(new CodeResult(MessageType.Success, "Done saving file."));
                            }
                            return(new CodeResult());
                        }
                        break;
                    }
                }
                throw new OperationCanceledException();

            // Delete a file on the SD card
            case 30:
                if (await SPI.Interface.Flush(code))
                {
                    string file         = code.GetUnprecedentedString();
                    string physicalFile = await FilePath.ToPhysicalAsync(file);

                    try
                    {
                        File.Delete(physicalFile);
                    }
                    catch (Exception e)
                    {
                        _logger.Debug(e, "Failed to delete file");
                        return(new CodeResult(MessageType.Error, $"Failed to delete file {file}: {e.Message}"));
                    }
                }
                throw new OperationCanceledException();

            // For case 32, see case 23

            // Return file information
            case 36:
                if (code.Parameters.Count > 0)
                {
                    if (await SPI.Interface.Flush(code))
                    {
                        string file = await FilePath.ToPhysicalAsync(code.GetUnprecedentedString(), FileDirectory.GCodes);

                        try
                        {
                            ParsedFileInfo info = await InfoParser.Parse(file);

                            string json = JsonSerializer.Serialize(info, JsonHelper.DefaultJsonOptions);
                            return(new CodeResult(MessageType.Success, "{\"err\":0," + json[1..]));
Exemple #18
0
        /// <summary>
        /// Process an M-code that should be interpreted by the control server
        /// </summary>
        /// <param name="code">Code to process</param>
        /// <returns>Result of the code if the code completed, else null</returns>
        public static async Task <CodeResult> Process(Commands.Code code)
        {
            switch (code.MajorNumber)
            {
            // Stop or Unconditional stop
            // Sleep or Conditional stop
            case 0:
            case 1:
                if (await SPI.Interface.Flush(code))
                {
                    using (await Print.LockAsync())
                    {
                        if (Print.IsFileSelected)
                        {
                            // M0/M1 may be used in a print file to terminate it
                            if (code.Channel != CodeChannel.File && !Print.IsPaused)
                            {
                                return(new CodeResult(MessageType.Error, "Pause the print before attempting to cancel it"));
                            }

                            // Invalidate the print file and make sure no more codes are read from it
                            code.CancellingPrint = true;
                            Print.Cancel();
                        }
                    }
                    break;
                }
                throw new OperationCanceledException();

            // List SD card
            case 20:
                if (await SPI.Interface.Flush(code))
                {
                    CodeParameter pParam    = code.Parameter('P');
                    string        directory = await FilePath.ToPhysicalAsync(pParam ?? "", FileDirectory.GCodes);

                    int startAt = Math.Max(code.Parameter('R') ?? 0, 0);

                    // Check if JSON file lists were requested
                    CodeParameter sParam = code.Parameter('S', 0);
                    if (sParam == 2)
                    {
                        string json = FileLists.GetFiles(pParam, directory, startAt);
                        return(new CodeResult(MessageType.Success, json));
                    }
                    if (sParam == 3)
                    {
                        string json = FileLists.GetFileList(pParam, directory, startAt);
                        return(new CodeResult(MessageType.Success, json));
                    }

                    // Print standard G-code response
                    Compatibility compatibility;
                    using (await Model.Provider.AccessReadOnlyAsync())
                    {
                        compatibility = Model.Provider.Get.Channels[code.Channel].Compatibility;
                    }

                    StringBuilder result = new StringBuilder();
                    if (compatibility == Compatibility.Me || compatibility == Compatibility.RepRapFirmware)
                    {
                        result.AppendLine("GCode files:");
                    }
                    else if (compatibility == Compatibility.Marlin || compatibility == Compatibility.NanoDLP)
                    {
                        result.AppendLine("Begin file list:");
                    }

                    int  numItems  = 0;
                    bool itemFound = false;
                    foreach (string file in Directory.EnumerateFileSystemEntries(directory))
                    {
                        if (numItems++ >= startAt)
                        {
                            string filename = Path.GetFileName(file);
                            if (compatibility == Compatibility.Marlin || compatibility == Compatibility.NanoDLP)
                            {
                                result.AppendLine(filename);
                            }
                            else
                            {
                                if (itemFound)
                                {
                                    result.Append(',');
                                }
                                result.Append($"\"{filename}\"");
                            }
                            itemFound = true;
                        }
                    }

                    if (compatibility == Compatibility.Marlin || compatibility == Compatibility.NanoDLP)
                    {
                        if (!itemFound)
                        {
                            result.AppendLine("NONE");
                        }
                        result.Append("End file list");
                    }

                    return(new CodeResult(MessageType.Success, result.ToString()));
                }
                throw new OperationCanceledException();

            // Select a file to print
            case 23:
            case 32:
                if (await SPI.Interface.Flush(code))
                {
                    string file = code.GetUnprecedentedString();
                    if (string.IsNullOrWhiteSpace(file))
                    {
                        return(new CodeResult(MessageType.Error, "Filename expected"));
                    }

                    string physicalFile = await FilePath.ToPhysicalAsync(file, FileDirectory.GCodes);

                    if (!File.Exists(physicalFile))
                    {
                        return(new CodeResult(MessageType.Error, $"Could not find file {file}"));
                    }

                    using (await Print.LockAsync())
                    {
                        if (code.Channel != CodeChannel.File && Print.IsPrinting)
                        {
                            return(new CodeResult(MessageType.Error, "Cannot set file to print, because a file is already being printed"));
                        }
                        await Print.SelectFile(physicalFile);
                    }

                    if (await code.EmulatingMarlin())
                    {
                        return(new CodeResult(MessageType.Success, "File opened\nFile selected"));
                    }
                    return(new CodeResult(MessageType.Success, $"File {file} selected for printing"));
                }
                throw new OperationCanceledException();


            // Resume a file print
            case 24:
                if (await SPI.Interface.Flush(code))
                {
                    using (await Print.LockAsync())
                    {
                        if (!Print.IsFileSelected)
                        {
                            return(new CodeResult(MessageType.Error, "Cannot print, because no file is selected!"));
                        }
                    }

                    // Let RepRapFirmware process this request so it can invoke resume.g. When M24 completes, the file is resumed
                    break;
                }
                throw new OperationCanceledException();

            // Set SD position
            case 26:
                if (await SPI.Interface.Flush(code))
                {
                    using (await Print.LockAsync())
                    {
                        if (!Print.IsFileSelected)
                        {
                            return(new CodeResult(MessageType.Error, "Not printing a file"));
                        }

                        CodeParameter sParam = code.Parameter('S');
                        if (sParam != null)
                        {
                            Print.FilePosition = sParam;
                        }
                    }

                    // P is not supported yet

                    return(new CodeResult());
                }
                throw new OperationCanceledException();

            // Report SD print status
            case 27:
                if (await SPI.Interface.Flush(code))
                {
                    using (await Print.LockAsync())
                    {
                        if (Print.IsFileSelected)
                        {
                            return(new CodeResult(MessageType.Success, $"SD printing byte {Print.FilePosition}/{Print.FileLength}"));
                        }
                        return(new CodeResult(MessageType.Success, "Not SD printing."));
                    }
                }
                throw new OperationCanceledException();

            // Begin write to SD card
            case 28:
                if (await SPI.Interface.Flush(code))
                {
                    int numChannel = (int)code.Channel;
                    using (await Commands.Code.FileLocks[numChannel].LockAsync())
                    {
                        if (Commands.Code.FilesBeingWritten[numChannel] != null)
                        {
                            return(new CodeResult(MessageType.Error, "Another file is already being written to"));
                        }

                        string file = code.GetUnprecedentedString();
                        if (string.IsNullOrWhiteSpace(file))
                        {
                            return(new CodeResult(MessageType.Error, "Filename expected"));
                        }

                        string prefix       = (await code.EmulatingMarlin()) ? "ok\n" : string.Empty;
                        string physicalFile = await FilePath.ToPhysicalAsync(file, FileDirectory.GCodes);

                        try
                        {
                            FileStream   fileStream = new FileStream(physicalFile, FileMode.Create, FileAccess.Write);
                            StreamWriter writer     = new StreamWriter(fileStream);
                            Commands.Code.FilesBeingWritten[numChannel] = writer;
                            return(new CodeResult(MessageType.Success, prefix + $"Writing to file: {file}"));
                        }
                        catch (Exception e)
                        {
                            _logger.Debug(e, "Failed to open file for writing");
                            return(new CodeResult(MessageType.Error, prefix + $"Can't open file {file} for writing."));
                        }
                    }
                }
                throw new OperationCanceledException();

            // End write to SD card
            case 29:
                if (await SPI.Interface.Flush(code))
                {
                    int numChannel = (int)code.Channel;
                    using (await Commands.Code.FileLocks[numChannel].LockAsync())
                    {
                        if (Commands.Code.FilesBeingWritten[numChannel] != null)
                        {
                            Stream stream = Commands.Code.FilesBeingWritten[numChannel].BaseStream;
                            Commands.Code.FilesBeingWritten[numChannel].Dispose();
                            Commands.Code.FilesBeingWritten[numChannel] = null;
                            stream.Dispose();

                            if (await code.EmulatingMarlin())
                            {
                                return(new CodeResult(MessageType.Success, "Done saving file."));
                            }
                            return(new CodeResult());
                        }
                        break;
                    }
                }
                throw new OperationCanceledException();

            // Delete a file on the SD card
            case 30:
                if (await SPI.Interface.Flush(code))
                {
                    string file         = code.GetUnprecedentedString();
                    string physicalFile = await FilePath.ToPhysicalAsync(file);

                    try
                    {
                        File.Delete(physicalFile);
                    }
                    catch (Exception e)
                    {
                        _logger.Debug(e, "Failed to delete file");
                        return(new CodeResult(MessageType.Error, $"Failed to delete file {file}: {e.Message}"));
                    }
                }
                throw new OperationCanceledException();

            // For case 32, see case 23

            // Return file information
            case 36:
                if (code.Parameters.Count > 0)
                {
                    if (await SPI.Interface.Flush(code))
                    {
                        string file = await FilePath.ToPhysicalAsync(code.GetUnprecedentedString());

                        try
                        {
                            ParsedFileInfo info = await FileInfoParser.Parse(file);

                            string json = JsonSerializer.Serialize(info, JsonHelper.DefaultJsonOptions);
                            return(new CodeResult(MessageType.Success, "{\"err\":0," + json.Substring(1)));
                        }
                        catch (Exception e)
                        {
                            _logger.Debug(e, "Failed to return file information");
                            return(new CodeResult(MessageType.Success, "{\"err\":1}"));
                        }
                    }
                    throw new OperationCanceledException();
                }
                break;

            // Simulate file
            case 37:
                if (await SPI.Interface.Flush(code))
                {
                    CodeParameter pParam = code.Parameter('P');
                    if (pParam != null)
                    {
                        string file = pParam;
                        if (string.IsNullOrWhiteSpace(file))
                        {
                            return(new CodeResult(MessageType.Error, "Filename expected"));
                        }

                        string physicalFile = await FilePath.ToPhysicalAsync(file, FileDirectory.GCodes);

                        if (!File.Exists(physicalFile))
                        {
                            return(new CodeResult(MessageType.Error, $"GCode file \"{file}\" not found\n"));
                        }

                        using (await Print.LockAsync())
                        {
                            if (code.Channel != CodeChannel.File && Print.IsPrinting)
                            {
                                return(new CodeResult(MessageType.Error, "Cannot set file to simulate, because a file is already being printed"));
                            }

                            await Print.SelectFile(physicalFile, true);

                            // Simulation is started when M37 has been processed by the firmware
                        }
                    }
                    break;
                }
                throw new OperationCanceledException();

            // Compute SHA1 hash of target file
            case 38:
                if (await SPI.Interface.Flush(code))
                {
                    string file         = code.GetUnprecedentedString();
                    string physicalFile = await FilePath.ToPhysicalAsync(file);

                    try
                    {
                        using FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read);

                        byte[] hash;
                        using System.Security.Cryptography.SHA1 sha1 = System.Security.Cryptography.SHA1.Create();
                        hash = await Task.Run(() => sha1.ComputeHash(stream), Program.CancelSource.Token);

                        return(new CodeResult(MessageType.Success, BitConverter.ToString(hash).Replace("-", string.Empty)));
                    }
                    catch (Exception e)
                    {
                        _logger.Debug(e, "Failed to compute SHA1 checksum");
                        if (e is AggregateException ae)
                        {
                            e = ae.InnerException;
                        }
                        return(new CodeResult(MessageType.Error, $"Could not compute SHA1 checksum for file {file}: {e.Message}"));
                    }
                }
                throw new OperationCanceledException();

            // Report SD card information
            case 39:
                if (await SPI.Interface.Flush(code))
                {
                    using (await Model.Provider.AccessReadOnlyAsync())
                    {
                        int index = code.Parameter('P', 0);
                        if (code.Parameter('S', 0) == 2)
                        {
                            if (index < 0 || index >= Model.Provider.Get.Storages.Count)
                            {
                                return(new CodeResult(MessageType.Success, $"{{\"SDinfo\":{{\"slot\":{index},present:0}}}}"));
                            }

                            Storage storage = Model.Provider.Get.Storages[index];
                            var     output  = new
                            {
                                SDinfo = new
                                {
                                    slot     = index,
                                    present  = 1,
                                    capacity = storage.Capacity,
                                    free     = storage.Free,
                                    speed    = storage.Speed
                                }
                            };
                            return(new CodeResult(MessageType.Success, JsonSerializer.Serialize(output, JsonHelper.DefaultJsonOptions)));
                        }
                        else
                        {
                            if (index < 0 || index >= Model.Provider.Get.Storages.Count)
                            {
                                return(new CodeResult(MessageType.Error, $"Bad SD slot number: {index}"));
                            }

                            Storage storage = Model.Provider.Get.Storages[index];
                            return(new CodeResult(MessageType.Success, $"SD card in slot {index}: capacity {storage.Capacity / (1000 * 1000 * 1000):F2}Gb, free space {storage.Free / (1000 * 1000 * 1000):F2}Gb, speed {storage.Speed / (1000 * 1000):F2}MBytes/sec"));
                        }
                    }
                }
                throw new OperationCanceledException();

            // Emergency Stop - unconditional and interpreteted immediately when read
            case 112:
                await SPI.Interface.RequestEmergencyStop();

                using (await Model.Provider.AccessReadWriteAsync())
                {
                    Model.Provider.Get.State.Status = MachineStatus.Halted;
                }
                return(new CodeResult());

            // Immediate DSF diagnostics
            case 122:
                if (code.Parameter('B', 0) == 0 && code.GetUnprecedentedString() == "DSF")
                {
                    CodeResult result = new CodeResult();
                    await Diagnostics(result);

                    return(result);
                }
                break;

            // Display message and optionally wait for response
            case 291:
                if (code.Parameter('S') == 2 || code.Parameter('S') == 3)
                {
                    throw new NotSupportedException();
                }
                break;

            // Save heightmap
            case 374:
                if (await SPI.Interface.Flush(code))
                {
                    string file         = code.Parameter('P', FilePath.DefaultHeightmapFile);
                    string physicalFile = await FilePath.ToPhysicalAsync(file, FileDirectory.System);

                    try
                    {
                        if (await SPI.Interface.LockMovementAndWaitForStandstill(code.Channel))
                        {
                            Heightmap map;
                            try
                            {
                                map = await SPI.Interface.GetHeightmap();
                            }
                            finally
                            {
                                await SPI.Interface.UnlockAll(code.Channel);
                            }

                            if (map.NumX * map.NumY > 0)
                            {
                                await map.Save(physicalFile);

                                string virtualFile = await FilePath.ToVirtualAsync(physicalFile);

                                using (await Model.Provider.AccessReadWriteAsync())
                                {
                                    Model.Provider.Get.Move.HeightmapFile = virtualFile;
                                }
                                return(new CodeResult(MessageType.Success, $"Height map saved to file {file}"));
                            }
                            return(new CodeResult());
                        }
                    }
                    catch (Exception e)
                    {
                        _logger.Debug(e, "Failed to save height map");
                        if (e is AggregateException ae)
                        {
                            e = ae.InnerException;
                        }
                        return(new CodeResult(MessageType.Error, $"Failed to save height map to file {file}: {e.Message}"));
                    }
                }
                throw new OperationCanceledException();

            // Load heightmap
            case 375:
                if (await SPI.Interface.Flush(code))
                {
                    string file         = code.Parameter('P', FilePath.DefaultHeightmapFile);
                    string physicalFile = await FilePath.ToPhysicalAsync(file, FileDirectory.System);

                    try
                    {
                        Heightmap map = new Heightmap();
                        await map.Load(physicalFile);

                        if (await SPI.Interface.LockMovementAndWaitForStandstill(code.Channel))
                        {
                            try
                            {
                                await SPI.Interface.SetHeightmap(map);
                            }
                            finally
                            {
                                await SPI.Interface.UnlockAll(code.Channel);
                            }

                            string virtualFile = await FilePath.ToVirtualAsync(physicalFile);

                            using (await Model.Provider.AccessReadWriteAsync())
                            {
                                Model.Provider.Get.Move.HeightmapFile = virtualFile;
                            }
                            return(new CodeResult(MessageType.Success, $"Height map loaded from file {file}"));
                        }
                    }
                    catch (Exception e)
                    {
                        _logger.Debug(e, "Failed to load height map");
                        if (e is AggregateException ae)
                        {
                            e = ae.InnerException;
                        }
                        return(new CodeResult(MessageType.Error, $"Failed to load height map from file {file}: {e.Message}"));
                    }
                }
                throw new OperationCanceledException();

            // Create Directory on SD-Card
            case 470:
                if (await SPI.Interface.Flush(code))
                {
                    string path = code.Parameter('P');
                    if (path == null)
                    {
                        return(new CodeResult(MessageType.Error, "Missing directory name"));
                    }
                    string physicalPath = await FilePath.ToPhysicalAsync(path);

                    try
                    {
                        Directory.CreateDirectory(physicalPath);
                    }
                    catch (Exception e)
                    {
                        _logger.Debug(e, "Failed to create directory");
                        return(new CodeResult(MessageType.Error, $"Failed to create directory {path}: {e.Message}"));
                    }
                }
                throw new OperationCanceledException();

            // Rename File/Directory on SD-Card
            case 471:
                if (await SPI.Interface.Flush(code))
                {
                    string from = code.Parameter('S');
                    string to   = code.Parameter('T');

                    try
                    {
                        string source = await FilePath.ToPhysicalAsync(from);

                        string destination = await FilePath.ToPhysicalAsync(to);

                        if (File.Exists(source))
                        {
                            if (File.Exists(destination) && code.Parameter('D', false))
                            {
                                File.Delete(destination);
                            }
                            File.Move(source, destination);
                        }
                        else if (Directory.Exists(source))
                        {
                            if (Directory.Exists(destination) && code.Parameter('D', false))
                            {
                                // This could be recursive but at the moment we mimic RRF's behaviour
                                Directory.Delete(destination);
                            }
                            Directory.Move(source, destination);
                        }
                        throw new FileNotFoundException();
                    }
                    catch (Exception e)
                    {
                        _logger.Debug(e, "Failed to rename file or directory");
                        return(new CodeResult(MessageType.Error, $"Failed to rename file or directory {from} to {to}: {e.Message}"));
                    }
                }
                throw new OperationCanceledException();

            // Store parameters
            case 500:
                if (await SPI.Interface.Flush(code))
                {
                    await Utility.ConfigOverride.Save(code);

                    return(new CodeResult());
                }
                throw new OperationCanceledException();

            // Print settings
            case 503:
                if (await SPI.Interface.Flush(code))
                {
                    string configFile = await FilePath.ToPhysicalAsync(FilePath.ConfigFile, FileDirectory.System);

                    if (File.Exists(configFile))
                    {
                        string content = await File.ReadAllTextAsync(configFile);

                        return(new CodeResult(MessageType.Success, content));
                    }

                    string configFileFallback = await FilePath.ToPhysicalAsync(FilePath.ConfigFileFallback, FileDirectory.System);

                    if (File.Exists(configFileFallback))
                    {
                        string content = await File.ReadAllTextAsync(configFileFallback);

                        return(new CodeResult(MessageType.Success, content));
                    }
                    return(new CodeResult(MessageType.Error, "Configuration file not found"));
                }
                throw new OperationCanceledException();

            // Set configuration file folder
            case 505:
                if (await SPI.Interface.Flush(code))
                {
                    string directory = code.Parameter('P'), physicalDirectory = await FilePath.ToPhysicalAsync(directory, "sys");

                    if (Directory.Exists(physicalDirectory))
                    {
                        string virtualDirectory = await FilePath.ToVirtualAsync(physicalDirectory);

                        using (await Model.Provider.AccessReadWriteAsync())
                        {
                            Model.Provider.Get.Directories.System = virtualDirectory;
                        }
                        return(new CodeResult());
                    }
                    return(new CodeResult(MessageType.Error, "Directory not found"));
                }
                throw new OperationCanceledException();

            // Set Name
            case 550:
                if (await SPI.Interface.Flush(code))
                {
                    // Verify the P parameter
                    string pParam = code.Parameter('P');
                    if (pParam.Length > 40)
                    {
                        return(new CodeResult(MessageType.Error, "Machine name is too long"));
                    }

                    // Strip letters and digits from the machine name
                    string machineName = string.Empty;
                    foreach (char c in Environment.MachineName)
                    {
                        if (char.IsLetterOrDigit(c))
                        {
                            machineName += c;
                        }
                    }

                    // Strip letters and digits from the desired name
                    string desiredName = string.Empty;
                    foreach (char c in pParam)
                    {
                        if (char.IsLetterOrDigit(c))
                        {
                            desiredName += c;
                        }
                    }

                    // Make sure the subset of letters and digits is equal
                    if (!machineName.Equals(desiredName, StringComparison.CurrentCultureIgnoreCase))
                    {
                        return(new CodeResult(MessageType.Error, "Machine name must consist of the same letters and digits as configured by the Linux hostname"));
                    }

                    // Hostname is legit - pretend we didn't see this code so RRF can interpret it
                    break;
                }
                throw new OperationCanceledException();

            // Configure filament
            case 703:
                if (await SPI.Interface.Flush(code))
                {
                    await Model.Updater.WaitForFullUpdate();

                    break;
                }
                throw new OperationCanceledException();

            // Set current RTC date and time
            case 905:
                if (await SPI.Interface.Flush(code))
                {
                    bool seen = false;

                    CodeParameter pParam = code.Parameter('P');
                    if (pParam != null)
                    {
                        if (DateTime.TryParseExact(pParam, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date))
                        {
                            System.Diagnostics.Process.Start("timedatectl", $"set-time {date:yyyy-MM-dd}").WaitForExit();
                            seen = true;
                        }
                        else
                        {
                            return(new CodeResult(MessageType.Error, "Invalid date format"));
                        }
                    }

                    CodeParameter sParam = code.Parameter('S');
                    if (sParam != null)
                    {
                        if (DateTime.TryParseExact(sParam, "HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime time))
                        {
                            System.Diagnostics.Process.Start("timedatectl", $"set-time {time:HH:mm:ss}").WaitForExit();
                            seen = true;
                        }
                        else
                        {
                            return(new CodeResult(MessageType.Error, "Invalid time format"));
                        }
                    }

                    if (!seen)
                    {
                        return(new CodeResult(MessageType.Success, $"Current date and time: {DateTime.Now:yyyy-MM-dd HH:mm:ss}"));
                    }
                }
                throw new OperationCanceledException();

            // Start/stop event logging to SD card
            case 929:
                if (await SPI.Interface.Flush(code))
                {
                    CodeParameter sParam = code.Parameter('S');
                    if (sParam == null)
                    {
                        using (await Model.Provider.AccessReadOnlyAsync())
                        {
                            return(new CodeResult(MessageType.Success, $"Event logging is {(Model.Provider.Get.State.LogFile != null ? "enabled" : "disabled")}"));
                        }
                    }

                    if (sParam > 0)
                    {
                        string file = code.Parameter('P', Utility.Logger.DefaultLogFile);
                        if (string.IsNullOrWhiteSpace(file))
                        {
                            return(new CodeResult(MessageType.Error, "Missing filename in M929 command"));
                        }

                        string physicalFile = await FilePath.ToPhysicalAsync(file, FileDirectory.System);

                        await Utility.Logger.Start(physicalFile);
                    }
                    else
                    {
                        await Utility.Logger.Stop();
                    }

                    return(new CodeResult());
                }
                throw new OperationCanceledException();

            // Update the firmware
            case 997:
                if (((int[])code.Parameter('S', new int[] { 0 })).Contains(0) && code.Parameter('B', 0) == 0)
                {
                    if (await SPI.Interface.Flush(code))
                    {
                        string iapFile, firmwareFile;
                        using (await Model.Provider.AccessReadOnlyAsync())
                        {
                            if (!string.IsNullOrEmpty(Model.Provider.Get.Electronics.ShortName))
                            {
                                // There are now two different IAP binaries, check which one to use
                                iapFile = Model.Provider.Get.Electronics.Firmware.Version.Contains("3.0beta")
                                        ? $"Duet3iap_spi_{Model.Provider.Get.Electronics.ShortName}.bin"
                                        : $"Duet3_SBCiap_{Model.Provider.Get.Electronics.ShortName}.bin";
                                firmwareFile = $"Duet3Firmware_{Model.Provider.Get.Electronics.ShortName}.bin";
                            }
                            else
                            {
                                // ShortName field is not present - this must be a really old firmware version
                                iapFile      = $"Duet3iap_spi.bin";
                                firmwareFile = "Duet3Firmware.bin";
                            }
                        }

                        iapFile = await FilePath.ToPhysicalAsync(iapFile, FileDirectory.System);

                        if (!File.Exists(iapFile))
                        {
                            return(new CodeResult(MessageType.Error, $"Failed to find IAP file {iapFile}"));
                        }

                        firmwareFile = await FilePath.ToPhysicalAsync(firmwareFile, FileDirectory.System);

                        if (!File.Exists(firmwareFile))
                        {
                            return(new CodeResult(MessageType.Error, $"Failed to find firmware file {firmwareFile}"));
                        }

                        using FileStream iapStream      = new FileStream(iapFile, FileMode.Open, FileAccess.Read);
                        using FileStream firmwareStream = new FileStream(firmwareFile, FileMode.Open, FileAccess.Read);
                        await SPI.Interface.UpdateFirmware(iapStream, firmwareStream);

                        return(new CodeResult());
                    }
                    throw new OperationCanceledException();
                }
                break;

            // Request resend of line
            case 998:
                throw new NotSupportedException();

            // Reset controller - unconditional and interpreteted immediately when read
            case 999:
                if (code.Parameters.Count == 0)
                {
                    await SPI.Interface.RequestReset();

                    return(new CodeResult());
                }
                break;
            }
            return(null);
        }