Перейти к содержанию
Fire Monkey от А до Я

Martifan

Пользователи
  • Постов

    396
  • Зарегистрирован

  • Посещение

  • Победитель дней

    16

Сообщения, опубликованные Martifan

  1. Вот обновленный и адаптированный вариант вашего кода для изменения приоритета потока на платформе POSIX в Delphi:

    uses
      Posix.Sched, Posix.Pthread, Posix.Errno;
    
    procedure SetThreadPriority;
    var
      Params: sched_param;
      ThreadId: pthread_t;
      Res: Integer;
    begin
      ThreadId := pthread_self();
      Params.sched_priority := 10; // устанавливаем приоритет 10
      Res := pthread_setschedparam(ThreadId, SCHED_FIFO, @Params);
      if Res <> 0 then
        raise Exception.CreateFmt('Error setting thread priority: %d', [Res]);
    end;

    Вы правильно указали, что для изменения приоритета потока может потребоваться выполнение приложения с правами администратора (root). Если ваше приложение должно работать без таких прав, убедитесь, что вы обрабатываете ошибки, возникающие при изменении приоритета, и рассмотрите возможность использования альтернативных методов изменения приоритета или оптимизации производительности.

    Также стоит учесть, что установка очень высокого приоритета потока может привести к проблемам с производительностью и стабильностью системы. Всегда тестируйте свое приложение на разных конфигурациях и устройствах, чтобы убедиться, что оно работает корректно и не вызывает нежелательных побочных эффектов.

  2. На Android 11 (API уровень 30) и выше, чтобы иметь полный доступ к внешнему хранилищу, вам нужно использовать разрешение MANAGE_EXTERNAL_STORAGE. Предоставление READ_EXTERNAL_STORAGE уже не даст полного доступа к файлам на устройстве.

    Чтобы запросить разрешение MANAGE_EXTERNAL_STORAGE, выполните следующие шаги:

    1. В вашем файле AndroidManifest.xml, добавьте разрешение:
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    1. Запросите разрешение у пользователя. Для этого создайте новый Intent и установите соответствующее действие:
    var
      Intent: JIntent;
    begin
      Intent := TJIntent.JavaClass.init;
      Intent.setAction(TJSettings.JavaClass.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
      TAndroidHelper.Activity.startActivity(Intent);
    end;
    1. Проверьте, предоставлено ли разрешение, используя метод Environment.isExternalStorageManager():
    uses
      ...,
      Androidapi.JNI.App, Androidapi.JNI.JavaTypes, Androidapi.JNI.Os;
    
    function IsExternalStorageManager: Boolean;
    begin
      Result := TJEnvironment.JavaClass.isExternalStorageManager(TAndroidHelper.Context);
    end;

    Обратите внимание, что MANAGE_ALL_FILES_ACCESS_PERMISSION доступно только на уровне API 30 и выше. Если ваше приложение также должно поддерживать более ранние версии Android, убедитесь, что вы проверяете версию Android перед вызовом этого кода:

    uses
      ...,
      Androidapi.JNI.Os;
    
    if TBuild_VERSION.JavaClass.SDK_INT >= 30 then
    begin
      // Запросите разрешение MANAGE_EXTERNAL_STORAGE
    end
    else
    begin
      // Запросите разрешение READ_EXTERNAL_STORAGE или WRITE_EXTERNAL_STORAGE
    end;

    По поводу отсутствия активити для действия android.settings.MANAGE_ALL_FILES_ACCESS_PERMISSION, возможно, это связано с конкретным устройством или версией Android. Вам может потребоваться использовать другой метод для запроса разрешения или обработать эту ситуацию соответствующим образом в вашем коде.

  3. Похоже, что вы пытаетесь пересоздать ресурсы DirectX после возникновения ошибки DXGI в Delphi с использованием FireMonkey (FMX). Ваш подход в целом верный, но возможно, вы упускаете некоторые важные шаги при пересоздании ресурсов.

    Вот несколько предложений, как можно улучшить ваш код:

    1. Обязательно убедитесь, что все объекты, использующие DirectX ресурсы, освобождают их перед вызовом DisposeResources. Это может включать текстуры, шейдеры, буферы и т.д.

    2. Может потребоваться вызов Device.Reset перед пересозданием общих ресурсов. Это зависит от того, каким образом вы обрабатываете ошибки DXGI в вашем коде. Вот пример, как это может выглядеть:

    procedure ResetDxEngine;
    var
      c: TCanvasD2D;
    begin
      // Освобождаем ресурсы для каждой канвы
      for c in Canvases do c.DisposeResources;
    
      // Сброс устройства
      if Assigned(TCanvasD2D.Device) then
        TCanvasD2D.Device.Reset;
    
      // Уничтожаем и создаем общие ресурсы
      TCanvasD2D.DestroySharedResources;
      TCanvasD2D.CreateSharedResources;
    
      // Создаем ресурсы для каждой канвы
      for c in Canvases do c.CreateResources;
    end;
    1. Если после выполнения этих шагов ваш код все еще не работает, возможно, проблема заключается в другой части вашего кода, связанной с обработкой ошибок DXGI. Проверьте, что вы корректно обрабатываете ошибки DXGI и вызываете ResetDxEngine только при необходимости.

    2. Обратите внимание, что некоторые ошибки DXGI могут быть связаны с оборудованием, и пересоздание ресурсов может не решить проблему. В таких случаях может потребоваться использование других методов восстановления, таких как переключение на программное устройство.

    Помимо этого, убедитесь, что ваш код корректно обрабатывает ошибки и исключения, возникающие при работе с DirectX, чтобы вы могли предоставить информацию пользователю или предпринять дополнительные действия для восстановления работы приложения.

  4. 5 минут назад, Игорь Маринин сказал:

    спасибо!  Androidapi.JNI.Support.Compat

    ну у меня в дельфи такого нет.. буду думать...

    Если у вас отсутствует модуль Androidapi.JNI.Support.Compat в вашей версии Delphi, то, вероятно, это связано с тем, что вы используете более старую версию Delphi, которая не включает этот модуль.

    В этом случае вы можете попробовать использовать классы, доступные в модуле Androidapi.JNI.Support, например, TJContextCompatMarshmallow для проверки разрешения в Android 6.0 и выше.

    uses
      Androidapi.Helpers, Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.JavaTypes,
      Androidapi.JNI.Support;
    
    procedure CheckAndRequestStoragePermission;
    begin
      if TJContextCompatMarshmallow.JavaClass.checkSelfPermission(TAndroidHelper.Context,
        JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE)) <> TJPackageManager.JavaClass.PERMISSION_GRANTED then
      begin
        TJActivityCompatMarshmallow.JavaClass.requestPermissions(TAndroidHelper.Activity,
          TJavaObjectArray<JString>.Create([TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE]),
          0);
      end
      else
        TDialogService.ShowMessage('Permission granted');
    end;

    Обратите внимание, что класс TJActivityCompatMarshmallow используется для запроса разрешения на чтение внешнего хранилища. Если вы используете другое разрешение, вам нужно использовать соответствующий класс из Androidapi.JNI.Support

  5. Причиной вылета приложения может быть ошибка в коде, которая вызывает неопределенное поведение при выполнении некоторых действий с TMemo. Ошибка может быть связана с попыткой доступа к освобожденной памяти или нарушением границ массива.

    Чтобы выявить причину ошибки, вы можете использовать отладчик в Delphi, который позволяет исследовать состояние программы во время выполнения и отслеживать переменные, значения и вызовы функций.

    Если вы не можете использовать отладчик для какой-либо причины, попробуйте добавить в ваш код обработку исключений, чтобы увидеть, какая ошибка возникает и в каком месте. Например, вы можете использовать следующий код:

    try
      // код, который может вызвать ошибку
    except
      on E: Exception do
        ShowMessage('Error: ' + E.Message);
    end;

    Этот код позволит отлавливать исключения и выводить сообщения об ошибках в приложении.

    Кроме того, вы можете попробовать использовать инструменты трассировки, такие как Logcat или сторонние инструменты для отслеживания ошибок в приложении на устройстве Android. Они могут помочь вам идентифицировать проблему и выявить причину вылета приложения.

  6. 2 минуты назад, Игорь Маринин сказал:

    а такой код вообще не вызывает никакого диалога на 13 андроиде:

                if (TJBuild_VERSION.JavaClass.SDK_INT >= 30)  then  
    
                if (TJEnvironment.JavaClass.isExternalStorageManager = false) then  begin
                    Intent := TJIntent.Create;
                    Intent.setAction(StringToJString('android.settings.MANAGE_ALL_FILES_ACCESS_PERMISSION'));
                    intent.setData(TJnet_Uri.JavaClass.parse(StringToJString('package:').concat(TAndroidHelper.Context.getPackageName)));
                    if (intent.resolveActivity(TAndroidHelper.Context.getPackageManager) <> nil) then TAndroidHelper.Context.startActivity(Intent);
                end;

     

    Код, который вы привели, предназначен для открытия экрана настроек разрешений в Android 11 и выше, где пользователь может предоставить разрешение на доступ к внешнему хранилищу. Однако, если у пользователя уже есть необходимые разрешения, экран настроек разрешений не будет открываться.

    Поэтому, если экран настроек разрешений не открывается, это может означать, что у пользователя уже есть необходимые разрешения. Если вы хотите убедиться в этом, вы можете добавить проверку разрешения в ваш код, как я показал в предыдущем ответе.

    if TJContextCompat.JavaClass.checkSelfPermission(TAndroidHelper.Context,
      JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE)) <> TJPackageManager.JavaClass.PERMISSION_GRANTED then
    begin
      // Разрешение не выдано, запрашиваем его
      // ...
    end
    else
    begin
      // Разрешение уже выдано
      // ...
    end;

    Если после проверки разрешения экран настроек разрешений все еще не открывается, проверьте, что вы используете правильное действие Intent. Вместо MANAGE_ALL_FILES_ACCESS_PERMISSION можно использовать другое действие, которое открывает экран настроек разрешений. Например, вы можете попробовать использовать ACTION_APPLICATION_DETAILS_SETTINGS.

  7. 10 минут назад, Игорь Маринин сказал:

    я понял, спасибо!

    спрашивал потому, что у меня в Androidapi.JNI.Support нет TJContextCompat

    ну и ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION то же нет нигде. но эту строковую константу я то могу заменить как писал  выше.

    у меня 11.3, странно.. 

    В версии Android API 28 (Android 9.0) и более новых версиях, класс TJContextCompat доступен в модуле Androidapi.JNI.Support.Compat, поэтому, для использования этого класса, вам нужно добавить этот модуль в uses секцию вашего кода.

    Пример использования TJContextCompat для проверки разрешения:

    uses
      Androidapi.Helpers, Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.JavaTypes,
      Androidapi.JNI.Support.Compat, FMX.DialogService;
    
    procedure CheckAndRequestStoragePermission;
    begin
      if TJContextCompat.JavaClass.checkSelfPermission(TAndroidHelper.Context,
        JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE)) <> TJPackageManager.JavaClass.PERMISSION_GRANTED then
      begin
        TJActivityCompat.JavaClass.requestPermissions(TAndroidHelper.Activity,
          TJavaObjectArray<JString>.Create([TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE]),
          0);
      end
      else
        TDialogService.ShowMessage('Permission granted');
    end;

    Обратите внимание, что в этом примере мы также используем TJActivityCompat, чтобы запросить разрешение на чтение внешнего хранилища, если разрешение еще не выдано. Этот класс также находится в модуле Androidapi.JNI.Support.Compat.

     
  8. 2 минуты назад, Игорь Маринин сказал:

    Intent := TJIntent.JavaClass.init(TJSettings.JavaClass.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);

    можно заменить на 

    Intent.setAction(StringToJString('android.settings.MANAGE_ALL_FILES_ACCESS_PERMISSION'));  ?

    TJSettings.JavaClass.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION и android.settings.MANAGE_ALL_FILES_ACCESS_PERMISSION - это одно и то же действие Intent, которое открывает настройки разрешений для приложения на Android 11 и выше.

    Вы можете использовать оба варианта в своем коде, в зависимости от того, что вам удобнее использовать.

  9. 1 минуту назад, Игорь Маринин сказал:

    спасибо! у вас 11.3 ?

    не могли бы уточнить, где описан TJContextCompat?

    а так же ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION ?

     

     

    TJContextCompat - это статический класс из модуля Androidapi.JNI.Support. Он содержит статические методы, которые обеспечивают совместимость с разными версиями Android, в том числе методы для проверки и запроса разрешений.

    ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION - это строковая константа, которая определяет действие Intent для отображения настроек разрешений приложения в Android 11 и выше. Она определена в классе android.provider.Settings и доступна через Androidapi.JNI.Provider в Delphi.

    В вашем случае эта константа используется для запуска настроек разрешений на чтение и запись во внешнее хранилище приложения на Android 11 и выше. После запуска настроек пользователь может выдать необходимые разрешения для приложения.

  10. uses
      Androidapi.Helpers, Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.JavaTypes,
      Androidapi.JNI.Support, FMX.DialogService;
    
    procedure RequestStoragePermission;
    var
      Intent: JIntent;
    begin
      if TJBuild_VERSION.JavaClass.SDK_INT >= 30 then
      begin
        if not TJEnvironment.JavaClass.isExternalStorageManager then
        begin
          Intent := TJIntent.Create;
          Intent := TJIntent.JavaClass.init(TJSettings.JavaClass.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
          intent.setData(TJnet_Uri.JavaClass.parse(StringToJString('package:').concat(TAndroidHelper.Context.getPackageName)));
          if intent.resolveActivity(TAndroidHelper.Context.getPackageManager) <> nil then
            TAndroidHelper.Context.startActivity(Intent);
        end;
      end
      else
      begin
        PermissionsService.RequestPermissions([JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE),
          JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE)],
          procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>)
          begin
            if (Length(AGrantResults) = 2) and (AGrantResults[0] = TPermissionStatus.Granted)
              and (AGrantResults[1] = TPermissionStatus.Granted) then
              TDialogService.ShowMessage('Permission granted')
            else
              TDialogService.ShowMessage('Permission denied');
          end);
      end;
    end;
    
    procedure CheckAndRequestStoragePermission;
    begin
      if TJBuild_VERSION.JavaClass.SDK_INT >= 30 then
      begin
        if TJContextCompat.JavaClass.checkSelfPermission(TAndroidHelper.Context,
          JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE)) <> TJPackageManager.JavaClass.PERMISSION_GRANTED
          then
          RequestStoragePermission
        else
          TDialogService.ShowMessage('Permission granted');
      end
      else
      begin
        if (PermissionsService.IsPermissionGranted(JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE))
          and PermissionsService.IsPermissionGranted(JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE))) then
          TDialogService.ShowMessage('Permission granted')
        else
          RequestStoragePermission;
      end;
    end;

     

  11. В 06.03.2023 в 19:11, usmanovtt сказал:

    Здравствуйте, коллеги. Использую RAD Studio 10.3 и FMX Linux 1.65.  Столкнулся с проблемой как говорится 'на ровном месте'. Приложение и Dll написаны с использованием FMX. Оставил только минимум (убрал не только функционал но и проверки). Нажатие на кнопку может происходить по несколько раз, проблем нет. А при закрытии приложения возникает AccessViolation. Настоящие приложение и библиотека более сложные, тут для примера оставил минимум. Первоначально в библиотеке было создание формы. Пробовал передавать в библиотеку Application и Screen. Ошибка при закрытии приложения та же. В итоге создал простые exe и dll, добавил минимум... Ошибка AV при закрытии приложения. В чем дело? Тот же код в VCL работает нормально. 

    Главное приложение  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

    unit formGetForm;

    interface
    uses
      System.SysUtils, System.Types, System.Classes, Winapi.Windows,
      FMX.Forms, FMX.Controls, FMX.Controls.Presentation, FMX.Types, FMX.StdCtrls;

    type
      P_Get = procedure; safecall;
      TfrmGetForm = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;

    var frmGetForm: TfrmGetForm;

    implementation
    {$R *.fmx}

    procedure TfrmGetForm.Button1Click(Sender: TObject);
    var  hDll:HMODULE;
           F_Get:P_Get;
    begin
       if(hDll=0) then
        begin
         hDll:=LoadLibrary('evTestForm.dll');
         F_Get := P_Get(GetProcAddress(hDll,'Get_F'));
         F_Get;
         FreeLibrary(hDll);
         hDll:=0;
        end;
    end;

    end.

    Dll  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    library evTestForm;
    uses
      FMX.Dialogs;

    {$R *.res}
    procedure Get_F;  safecall;
    begin
     ShowMessage('+++');
    end;

    exports   Get_F;

    begin
    end.

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    Если заменю  FMX.Dialogs; на  VCL.Dialogs; приложение закрывается без AV. 

     

    В FMX для работы с диалогами следует использовать FMX.DialogService. В данном случае проблема возникает из-за того, что в библиотеке используется FMX.Dialogs, который может работать некорректно с главным потоком приложения.

    uses
      FMX.DialogService;
    
    procedure Get_F;  safecall;
    begin
      TDialogService.ShowMessage('+++');
    end;

    Также обратите внимание, что в вашем примере вы вызываете FreeLibrary(hDll); в блоке условия if, что может привести к проблемам, если библиотека уже была загружена ранее. Вы можете перенести вызов FreeLibrary за пределы блока условия, чтобы быть уверенным, что библиотека будет освобождена, когда ее больше не нужно.

     

  12. Проблема заключается в том, что вызов функции Sleep блокирует главный поток приложения, что приводит к остановке обработки сообщений в очереди сообщений Windows. В результате функция SendMessage не сможет отправить сообщение до тех пор, пока главный поток не будет освобожден и сможет продолжить обработку очереди сообщений.

    Для решения этой проблемы необходимо использовать асинхронный подход и выполнять задержку в отдельном потоке, чтобы не блокировать главный поток приложения. Например, можно использовать класс TTask из библиотеки Delphi для выполнения задержки в отдельном потоке.

    Пример использования TTask для выполнения задержки в отдельном потоке:

    uses
      System.Threading;
    
    procedure SendResult(ResultCode: Integer);
    var
      Message: TMessage<Integer>;
    begin
      // отправляем результат в другой intent
      // ...
      
      // отправляем результат в главную форму
      Message := TMessage<Integer>.Create(ResultCode);
      TMessageManager.DefaultManager.SendMessage(nil, Message);
    end;
    
    procedure ScanResultHandler(const AData: TArray<TScanResult>);
    var
      ResultCode: Integer;
    begin
      // обработка сканера
      // ...
      
      // задержка в отдельном потоке
      TTask.Run(
        procedure
        begin
          Sleep(10000);
          SendResult(ResultCode);
        end);
    end;

    В этом примере мы использовали анонимную процедуру, чтобы выполнить задержку в отдельном потоке. Задержка выполняется с помощью функции Sleep, а затем мы вызываем функцию SendResult, чтобы отправить результат в другой intent и в главную форму через TMessageManager.DefaultManager.SendMessage. Поскольку задержка выполняется в отдельном потоке, главный поток приложения не блокируется, и сообщения в очереди обрабатываются нормально.

  13. Для получения информации о том, какой метод блокировки экрана используется на устройстве Android, можно воспользоваться классом KeyguardManager. Этот класс позволяет проверить, заблокирован ли экран на устройстве и какой именно метод блокировки экрана используется.

    Пример использования KeyguardManager в Delphi:

    uses
      Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.Os, Androidapi.JNI.Provider,
      Androidapi.JNI.Widget, Androidapi.Helpers, Androidapi.JNI.JavaTypes;
    
    function IsDeviceLocked: Boolean;
    var
      KeyguardManager: JKeyguardManager;
    begin
      KeyguardManager := TJKeyguardManager.Wrap
        ((SharedActivityContext.getSystemService(TJContext.JavaClass.KEYGUARD_SERVICE) as ILocalObject).GetObjectID);
      Result := KeyguardManager.isKeyguardLocked();
    end;
    
    function GetKeyguardType: Integer;
    var
      KeyguardManager: JKeyguardManager;
    begin
      KeyguardManager := TJKeyguardManager.Wrap
        ((SharedActivityContext.getSystemService(TJContext.JavaClass.KEYGUARD_SERVICE) as ILocalObject).GetObjectID);
      if KeyguardManager.isKeyguardSecure() then
      begin
        if KeyguardManager.isDeviceSecure() then
          Result := 2 // Блокировка по биометрическим данным
        else
          Result := 1; // Блокировка по паролю, пин-коду или рисунку
      end
      else
        Result := 0; // Блокировка не настроена
    end;

    Функция IsDeviceLocked проверяет, заблокирован ли экран на устройстве в настоящее время. Если экран заблокирован, функция возвращает True, в противном случае возвращает False.

    Функция GetKeyguardType позволяет получить тип блокировки экрана на устройстве. Если на устройстве настроена блокировка экрана по биометрическим данным, функция возвращает 2. Если на устройстве настроена блокировка экрана по паролю, пин-коду или рисунку, функция возвращает 1. Если блокировка экрана не настроена, функция возвращает 0.

    Обратите внимание, что для использования KeyguardManager необходимо включить соответствующее разрешение в файле манифеста вашего приложения:

    <uses-permission android:name="android.permission.USE_BIOMETRIC"/>

     

  14. Для установки приоритета потока в Linux в Delphi можно использовать функцию pthread_setschedparam(). Эта функция позволяет задать приоритет потока в соответствии с POSIX-стандартом.

    Пример использования функции pthread_setschedparam() для установки приоритета потока можно найти в следующем коде:

    uses
      Posix.Sched;
    
    var
      Params: sched_param;
      ThreadId: pthread_t;
    begin
      ThreadId := pthread_self();
      Params.sched_priority := 10; // устанавливаем приоритет 10
      if pthread_setschedparam(ThreadId, SCHED_FIFO, @Params) <> 0 then
        raise Exception.Create('Error setting thread priority');
    end;

    В этом примере мы устанавливаем приоритет потока на уровне 10 с помощью структуры sched_param. Далее мы используем функцию pthread_setschedparam() для установки приоритета нашему потоку, и если функция возвращает значение отличное от 0, то возникает исключение.

    Обратите внимание, что установка приоритета потока может быть опасной, поскольку это может привести к проблемам с производительностью системы или блокировке других потоков. Поэтому необходимо использовать эту функцию осторожно и только в случае крайней необходимости.

  15. Здравствуйте!

    Для разбора звукового файла WAV в Delphi можно использовать стандартные средства работы с аудиофайлами из библиотеки Windows API или сторонние библиотеки, такие как BASS или FMOD.

    Пример чтения и воспроизведения звукового файла WAV с использованием Windows API можно найти в следующем коде:

    var
      WaveFormat: TWAVEFORMATEX;
      MMResult: MMRESULT;
      HWaveOut: HWAVEOUT;
      WaveHeader: TWAVEHDR;
      WaveData: Pointer;
      WaveSize: DWORD;
    begin
      MMResult := waveInOpen(@HWaveOut, WAVE_MAPPER, @WaveFormat, 0, 0, CALLBACK_NULL);
      if MMResult <> MMSYSERR_NOERROR then
        raise Exception.CreateFmt('Error opening audio device. Error code: %d', [MMResult]);
    
      try
        WaveData := LoadWaveData('audio.wav', WaveSize); // функция загрузки данных из WAV файла
        ZeroMemory(@WaveHeader, SizeOf(TWAVEHDR));
        WaveHeader.dwBufferLength := WaveSize;
        WaveHeader.lpData := WaveData;
        MMResult := waveOutPrepareHeader(HWaveOut, @WaveHeader, SizeOf(TWAVEHDR));
        if MMResult <> MMSYSERR_NOERROR then
          raise Exception.CreateFmt('Error preparing audio data. Error code: %d', [MMResult]);
          
        try
          MMResult := waveOutWrite(HWaveOut, @WaveHeader, SizeOf(TWAVEHDR));
          if MMResult <> MMSYSERR_NOERROR then
            raise Exception.CreateFmt('Error playing audio. Error code: %d', [MMResult]);
            
          while waveOutUnprepareHeader(HWaveOut, @WaveHeader, SizeOf(TWAVEHDR)) = WAVERR_STILLPLAYING do
            Sleep(10);
        finally
          FreeMem(WaveData);
        end;
      finally
        waveOutClose(HWaveOut);
      end;
    end;

    Для анализа звукового файла можно использовать сторонние библиотеки, такие как BASS или FMOD. Например, для работы с BASS можно использовать следующий код:

    uses
      Bass;
    
    var
      Stream: HSTREAM;
      Info: BASS_CHANNELINFO;
      Frequency: Integer;
    begin
      if not BASS_Init(-1, 44100, 0, 0, nil) then
        raise Exception.Create('Error initializing audio system');
    
      try
        Stream := BASS_StreamCreateFile(False, 'audio.wav', 0, 0, BASS_SAMPLE_FLOAT or BASS_STREAM_DECODE);
        if Stream = 0 then
          raise Exception.Create('Error creating audio stream');
    
        try
          BASS_ChannelGetInfo(Stream, Info);
          Frequency := Info.freq;
          // далее можно использовать функции BASS для анализа звукового файла
        finally
          BASS_StreamFree(Stream);
        end;
      finally
        BASS_Free();
      end;
    end;

     

  16. Всем доброго времени сутки.
    Просьба помогите протестировать шифрацию, то есть я дам вам шифровку кто расшифрует заплачу 500$ вот зашифрованы текст:

    ba3xDmsH/xHtIPa7KO3uDQHnuZzXAxS0fEfXmLgt7ISasdETm9Oj9s/VGpXH//egpN6Rs0vJmZnONQtf73p1k8sYYuNO7sC5/LNvSfwucMw1EYiujj2Nrya34lORM7pp/vsR2PYGeaLqbeSFk6RtQq0X5Kj2n97bagRxlLAJNzh2VTkEESWn/W5YIhzucdNdLlWmz/5F2zltM0NkzOeBwprugxU0GQ0tHcKh4fiQKCD8DZyitZcRIgbuYYwoGEmJddedm+GhUhN8RB6ljCxKuwpXz2QdmAyiW97bAbOgUK/oVHsEZ5gLIr7NmdgDQ9t8XhrgmaZcO/bsYkkcBUJzLTUbqh4l+Sq4zWwFaCMyJTsuQvrDAEbBqY8MCvPmNeD1aS/ey79SAnKrQp2T170lIAGQwZq7iP7YQs8VWsYsP2QlY0vTM86T852bEHL/Oon9grmUptD4WTIGUakSNxJ70jySuOKQgZOME3S+9BcbpPx/c8lO32wH6FPe9RlMZaYf9RHKUsaPOMFPV+xFGJ2OhNeItJkEd7qvp9aCj/h7zvdrQTCi5IFdsEWxEhRz2f1dxGciI5qc3k3Onvor55zCyA==

    всем спасибо за помощь 

  17. Всем привет.
    Установил Delphi Sydney,

    запустил пустую приложению под iOS и у меня запускается так:

    117804313_1339652816240224_4343907503265313774_n.jpg

    как убрать эти черные панели верх и внизу? 

    P.S.. под Delphi Rio все хорошо работает 

    Спасибо за любой ответ

  18. Здравствуйте, Сделал в аппликацию пуш уведомление все работает но есть одна проблема, когда доходит уведомление нету звука, хотя настройках показывает что звук включен, скрипт для отправки уведомления:

    {
      "to": "fetrOVKDF8Q:*****",
        "notification" : {
        "body" : "Hey!? Checkout my custom notification",
        "title" : "Hey!? Checkout my custom notification",
        "Sound" : "default",
        "badge": "1"
        }
    }

    может кто знает как включить звук заранее спасибо

  19.  

    Всем привет. Помогите перевести код на Delphi

    C# (Xamarin):

    public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
    {
        //DeviceToken = Regex.Replace(deviceToken.ToString(), "[^0-9a-zA-Z]+", "");
        //Replace the above line whick worked up to iOS12 with the code below:
        byte[] bytes = deviceToken.ToArray<byte>();
        string[] hexArray = bytes.Select(b => b.ToString("x2")).ToArray();
        DeviceToken = string.Join(string.Empty, hexArray);
    }
    let deviceTokenString = deviceToken.map { String(format: "%02x", $0) }.joined()

    заранее спасибо

×
×
  • Создать...