/// <summary> /// Разбирает ответ от сервера /// По неизвестной причине в ответ на команду от сервера может прийти не полный ответ /// При отправке следующе команды можно получить продолжение ответа на предыдущую комаду /// при этом не обязательно овет на предыдущую команду будет заверщён. /// /// Обработка ответов сервера выполняется по следующему алгоритму. /// Все ответы полученные от сервера помещаются в буфер. /// После полученя каждого ответа анализируется содержимое буфера. /// Если буфер содержит полны ответ то этот полный ответ связывается с соответствующе командой /// и передается на обработку. /// /// </summary> /// <param name="responce"></param> /// <returns></returns> private string ParceResponse(string response) { MpdResponseCollection mpdresponse = new MpdResponseCollection(); // Oтвет при ошибке начинается с ASC и заканчивается \n // Ответ при нормальном завершении заканчивается OK\n // Проверка 1 // Строка начинается с символов OK\n - это значит что в начале строки содержится ответ // об успешном выполнении команды не возвращающей данных // Просто убираем этот ответ из входной строки if (response.StartsWith("OK\n", StringComparison.Ordinal)) { response = response.Remove(0, 3); mpdresponse.Command = _SentCommandQueue.Dequeue(); mpdresponse.Keyword = MpdResponseCollection.ResponseKeyword.Ok; Task.Run(() => HandleResponse(mpdresponse)); } // Проверка 2 // Строка содержит символы \nOK\n - это значит что строка содержит полный ответ // об успешном выполнении команды возвращающей данные // Забираем этот ответ из входной строки и разбираем его if (response.Contains("\nOK\n")) { //Забираем из входной строки подстроку от начала до до символов ОК (вместе с ОК) int nextresponsestart = response.IndexOf("\nOK\n", StringComparison.Ordinal) + 4; string currentresponce = response.Substring(0, nextresponsestart); response = response.Remove(0, nextresponsestart); string[] lines = currentresponce.Split('\n'); for (int i = 0; i < lines.Length - 2; i++) { mpdresponse.Add(lines[i]); } mpdresponse.Keyword = MpdResponseCollection.ResponseKeyword.Ok; mpdresponse.Command = _SentCommandQueue.Dequeue(); Task.Run(() => HandleResponse(mpdresponse)); } // Проверка 3 // Строка содержит символы ACK - это значит что строка содержит ответ с информацией // об ошибке при выполнении команды // Забираем этот ответ из входной строки и cообщаем об ошибке if (response.StartsWith("ACK", StringComparison.Ordinal)) { int newresponsestart = response.IndexOf("\n", StringComparison.Ordinal) + 1; string currentresponse = response.Substring(0, newresponsestart); response = response.Remove(0, newresponsestart); NotifyError("Server return error : \n" + currentresponse); return(response); } return(response); }
/// <summary> /// Read server responces and convert them into data objects /// </summary> private async Task HandleResponse(MpdResponseCollection response) { //bool handleResponseCriticalError = false; string errorMessage = string.Empty; try { switch (response.Command.Op) { case "update": // в ответ на команду сервер возвращает" "updating_db: 1\n" (Реализовано) case "stats": _Statistics.Update(response); break; case "status": _Status.Update(response); break; // Реализовано case "currentsong": _CurrentSong.Update(response); break; case "lsinfo": if (response.Count > 0) { // Каталог не пустой string currentfolder = string.Empty; if (CurrentFolder.Length != 0) { currentfolder = CurrentFolder + "\\"; } // Создаём временный список файлов и заполняем его данными из ответв сервера ObservableObjectCollection <File> filelist = new ObservableObjectCollection <File>(_mainPage); filelist.Update(response); if (_filelistUpdatInProcess) { _filelistCancelUpdate = true; while (_filelistUpdatInProcess) { await Task.Delay(TimeSpan.FromMilliseconds(100)); } // while (_filelistUpdatInProcess); _filelistCancelUpdate = false; } await UpdateFileList(filelist); } else { // Каталог не содержит файлов _FileList.ClearAndNotify(); } break; case "list": switch (response.Command.Argument1) { case "genre": _Genres.Update(response); break; case "artist": _Artists.Update(response); break; case "album": _Albums.Update(response); break; case "title": _Tracks.Update(response); break; } break; case "search": _Tracks.Update(response); break; case "playlistinfo": _Playlist.Update(response); break; case "listplaylists": _SavedPlaylists.Update(response); break; case "outputs": if (response.Count > 0) { _Outputs.Update(response); } break; case "config": break; default: break; } if (response.Command.Op != "status") { NotifyCommandCompletion(response.Command.Op, "OK", response.Error); } } catch (BalboaNullValueException be) { _Terminating = true; errorMessage = string.Format(_resldr.GetString("NullValueExceptionMsg"), be.VariableName, be.MethodName, be.FileName, be.LineNumber); } catch (BalboaException be) { _Terminating = true; errorMessage = string.Format(_resldr.GetString("BalboaExceptionMsg"), be.MethodName, be.FileName, be.LineNumber, be.Message); } catch (Exception e) { _Terminating = true; string exceptionMessage = e.Message.Contains("\r\n") ? e.Message.Substring(0, e.Message.IndexOf("\r\n")) : e.Message; errorMessage = string.Format(_resldr.GetString("UnexpectedServerError"), exceptionMessage); } finally { if (_Terminating) { //await Halt(); NotifyCriticalError(errorMessage); } } }