as

Settings
Sign out
Notifications
Alexa
Amazonアプリストア
AWS
ドキュメント
Support
Contact Us
My Cases
開発
設計と開発
公開
リファレンス
サポート

Vegaメディアコントロールについて

Vegaメディアコントロールについて

このガイドでは、Vegaメディアコントロールを実装するアプリの実装例について説明します。

VegaメディアコントロールAPIリファレンス

このAPIに関するリファレンスドキュメントについては、amzn/kepler-media-controlsを参照してください。

Vegaメディアコントロールの前提条件

次に挙げる前提条件は、メディアプロバイダーアプリの開発にのみ適用され、クライアントメソッドを使用する場合は適用されません。クライアントメソッドを使用する場合は、事前に、アプリマニフェストを更新して、VegaメディアコントロールAPIを使用する意図を明示的に宣言する必要があります。マニフェストエントリを変更するときは、以下の例に示すように、com.amazondeveloper.media.sampleをアプリの実際のパッケージIDに必ず置き換えてください。この手順を踏むことにより、アプリがVegaメディアコントロールAPIと対話するように正しく構成されます。

クリップボードにコピーしました。

[package]
title = "<アプリタイトル>"
id = "com.amazondeveloper.media.sample"

[components]
[[components.interactive]]
id = "com.amazondeveloper.media.sample.main"
launch-type = "singleton"
# カテゴリ "com.amazon.category.kepler.media" は主要コンポーネントのみに必要で、マニフェストのextras
# セクションの "interface.provider" キーを使用して識別されます。
categories = ["com.amazon.category.kepler.media"]
runtime-module = "/com.amazon.kepler.keplerscript.runtime.loader_2@IKeplerScript_2_0"

[[extras]]
key = "interface.provider"
component-id = "com.amazondeveloper.media.sample.main"

[extras.value.application]
[[extras.value.application.interface]]
interface_name = "com.amazon.kepler.media.IMediaPlaybackServer"
command_options = [
    "StartOver",
    "Previous",
    "Next",
    "SkipForward",
    "SkipBackward",
    <サポート されている 他のコマンドを 挿入>
]
attribute_options = [AudioAdvanceMuted", <サポートされている属性オプションをすべて挿入>]
features = ["AdvancedSeek", "VariableSpeed", "AudioTracks", "TextTracks", <サポートされている他の機能を挿入>]

Vegaメディアコントロールのインストールと設定

APIを使用するには、package.jsonに次の依存関係を追加します。

クリップボードにコピーしました。

"@amazon-devices/kepler-media-controls": "^1.0.0",
"@amazon-devices/kepler-media-types": "^1.0.0"

Vegaメディアコントロールの一般的なユースケース

メディアコンテンツプロバイダーアプリの場合

プロバイダーアプリでメディアセッションの状態を管理するには、MediaPlayerStateクラスを実装します。このクラスは、メディアセッションに必要なすべてのプロパティをカプセル化します。これには、再生状態、トラック情報、再生時間、現在位置、再生速度、使用可能なメディア操作などが含まれます。MediaPlayerStateクラスには、メディアセッションの状態が変化したときにこれらのプロパティを更新するメソッドが用意されています。これらのメソッドに加えてgetServerState()などのメソッドを含めると、現在のプロパティ値に基づいて有効なMediaSessionStateオブジェクトを構築して返すことができます。メディアセッションが変更されたときに必ずMediaPlayerStateインスタンスを更新すると、MediaSessionStateオブジェクトにメディアプレーヤーの最新状態を正確に反映でき、これにより状態管理が一元化されて同期が簡単になります。複数のビデオの同時再生をサポートするメディアプロバイダーの場合、セッションごとに個別のMediaPlayerStateオブジェクトを管理し、インスタンスごとにMSessionIDが正しく更新されていることを確認してください。このアプローチにより、アプリ内の複数のメディアセッションを効率的に管理できます。

クリップボードにコピーしました。

import {
  Action,
  ICapabilities,
  IPlaybackState,
  PlaybackStatus,
  IPlaylistState,
  RepeatMode,
  IControl,
  MediaSessionState,
  ITimeValue,
  IPlaybackPosition,
  IMediaSessionId,
  IMediaInfo,
  ILocale,
} from '@amazon-devices/kepler-media-controls';
import {MediaId} from '@amazon-devices/kepler-media-types';

export class MediaPlayerState {
  playbackStatus: PlaybackStatus = PlaybackStatus.NOT_PLAYING;
  playbackSpeed: number = 1.0;
  playbackState: IPlaybackState | undefined;
  updatedAtTime: ITimeValue = {seconds: 1702965600, nanoseconds: 0};
  currentPosition: ITimeValue = {seconds: 10, nanoseconds: 999999999};
  mediaInfo: IMediaInfo | undefined;
  playbackPosition: IPlaybackPosition = {
    updatedAtTime: {seconds: 1702965600, nanoseconds: 0},
    position: {seconds: 10, nanoseconds: 999999999},
  };

  forwardSkipSteps: ITimeValue[] = [
    {seconds: 1, nanoseconds: 0},
    {seconds: 2, nanoseconds: 0},
    {seconds: 3, nanoseconds: 0},
    {seconds: 4, nanoseconds: 0},
  ];

  backwardSkipSteps: ITimeValue[] = [
    {seconds: 1, nanoseconds: 0},
    {seconds: 2, nanoseconds: 0},
    {seconds: 3, nanoseconds: 0},
    {seconds: 4, nanoseconds: 0},
  ];

  mId: MediaId = {contentId: 'com.foo.bar', catalogName: 'sample-catalog-v1'};
  mSessionId: IMediaSessionId = {id: 0};

  currentSupportedActions: Action[] = [
    Action.PLAY,
    Action.PAUSE,
    Action.STOP,
    new Action('ENABLE_XRAY'),
    new Action('DISABLE_XRAY'),
  ];
  currentSupportedSpeeds: number[] = [
    -2.0, -1.5, -1.0, -0.5, 0.5, 1.0, 1.5, 2.0,
  ];
  currentSupportedRatings: number[] = [0.0, 1.0];
  capabilities: ICapabilities | undefined;
  locale: ILocale | undefined;

  repeatMode: RepeatMode = RepeatMode.REPEAT_TRACK;
  enableShuffle: boolean = true;
  playlistState: IPlaylistState | undefined;

  xRayControlName: string = 'X-ray';
  xRayControlStateOff: string = 'off';
  xRayControlStateOn: string = 'on';
  controls: IControl[] | undefined;

  serverState: MediaSessionState | undefined;

  getServerState() {
    this.playbackState = {
      playbackStatus: this.playbackStatus,
      playbackSpeed: this.playbackSpeed,
      position: this.playbackPosition,
    };

    this.capabilities = {
      actions: this.currentSupportedActions,
      speeds: this.currentSupportedSpeeds,
      ratings: this.currentSupportedRatings,
      forwardSkipSteps: this.forwardSkipSteps,
      backwardSkipSteps: this.backwardSkipSteps,
    };

    this.playlistState = {
      repeatMode: this.repeatMode,
      shuffle: this.enableShuffle,
    };

    this.controls = [
      {name: this.xRayControlName, state: this.xRayControlStateOff},
    ];

    this.locale = {
      identifier: 'en-US',
    };

    this.mediaInfo = {
      id: this.mId,
      hasVideo: true,
      availableAudioTracks: [
        {id: '0', displayName: 'English', language: this.locale},
      ],
      availableTextTracks: [
        {id: '0', displayName: 'English', language: this.locale},
      ],
    };

    this.serverState = {
      id: this.mSessionId,
      playbackState: this.playbackState,
      capabilities: this.capabilities,
      playlistState: this.playlistState,
      controls: this.controls,
    };

    return this.serverState;
  }
}

メディアコントロール機能を実装するには、IMediaControlHandlerAsyncインターフェイスを実装するMediaControlHandlerAsyncクラスを作成します。このクラスには、メディア再生コントロールを管理するためのhandlePlayhandlePauseなどのコールバック関数が用意されています。これらの関数は、TypeScriptにおけるPromiseベースのメソッドを使用してノンブロッキング実行を保証します。また、このクラスには、以前に作成したMediaPlayerStateクラスを使用してメディアセッションの状態を非同期的に返すコールバックも実装されています。

記載されているコード例では、当メソッドのサブセットのみを実装しています。完全な実装には、IMediaControlHandlerAsyncインターフェイスのすべてのメソッドが含まれます。ほとんどのコールバック関数は、要求されたアクションを実行するセッション識別子を示すIMediaSessionIDインターフェイスオブジェクトのインスタンスを受け取ります。このことは、メディアプロバイダーアプリが複数のセッションをサポートしている場合に特に重要です。SessionIdの値が空白あるいは未設定の場合、デフォルトで、プロバイダーアプリはデフォルトのセッションでアクションを実行します。このアプローチにより、アプリ内の単一または複数のメディアセッションにおいて、メディアコントロールリクエストが適切に処理されるようになります。

MediaControlHandlerAsyncクラスはHandleGetMetadataInfoメソッドを実装する必要があります。後者のメソッドはiMediaControlHandlerAsyncインターフェイス内に定義されているメソッドの1つです。このメソッドは、当該のセッションで現在再生されているメディアのメタデータを返す処理を行います。メディアのメタデータ情報は、IMediaMetadataデータオブジェクトを使用して表されます。このデータオブジェクトには、メディアID、作曲家、アーティスト、再生ソースなどのさまざまなプロパティが含まれています。記載されているコード例では、HandleGetMetadataInfoの実装によって、IMediaMetadataオブジェクトを作成して返す方法が示されています。わかりやすくするために、この例ではインラインオブジェクトを使用してメタデータを表します。ただし、本番環境では、IMediaMetadataデータオブジェクトを実装する独立したクラスを作成するアプローチをお勧めします。この独立したクラスは、メディアメタデータを処理するための専用のデータオブジェクトとして機能し、メディア属性のより包括的表現を可能にすると同時に、コードの構造を改善して保守しやすくします。

MediaControlHandlerAsyncクラスコンストラクターは、メディアコントロール機能をセットアップする上で重要な役割を果たします。このコンストラクターは、MediaControlServerComponentAsyncの単一インスタンスを作成します。これは、メディアコントロールの操作を非同期的に処理するコアコンポーネントの役割を果たします。このコンストラクターでは、IComponentInstanceオブジェクトを登録するステップが重要になります。このオブジェクトはパラメーターとしてコンストラクターに渡された後、MediaControlServerComponentAsyncインスタンスに登録されます。登録プロセスが重要な理由は、メディアコントロールハンドラーと、メディアコントロールコールバックを受信するアプリ内の特定コンポーネントとのリンクが確立されるためです。複数のコンポーネントを含むアプリでは、この登録が特に重要になります。適切なIComponentInstanceMediaControlHandlerAsyncコンストラクターに渡すことで、メディアコントロールコールバックが適切なコンポーネントに確実に送信されます。ターゲットを絞ったこのアプローチは、メディアコントロールがアプリの意図した部分のみに作用するようにし、混乱を防ぎます。

クリップボードにコピーしました。

import {
  Action,
  IMediaControlHandlerAsync,
  IMediaSessionId,
  PlaybackStatus,
  RepeatMode,
  ITimeValue,
  ITrack,
  IMediaMetadata,
  MediaSessionState,
} from '@amazon-devices/kepler-media-controls';

import {MediaId} from '@amazon-devices/kepler-media-types';

import {IComponentInstance} from '@amazon-devices/react-native-kepler';

import {
  IMediaControlServerAsync,
  MediaControlServerComponentAsync,
} from '@amazon-devices/kepler-media-controls';

import {MediaPlayerState} from './MediaPlayerState';

export class MediaControlHandlerAsync implements IMediaControlHandlerAsync {
  mediaControlServer: IMediaControlServerAsync;
  mediaPlayerState: MediaPlayerState;

  constructor(componentInstance: IComponentInstance) {
      MediaControlServerComponentAsync.getOrMakeServer();
    this.mediaPlayerState = new MediaPlayerState();

    this.mediaControlServer.setHandlerForComponent(this, componentInstance);
    this.setMediaSessionState();
  }

  setMediaSessionState() {
    const mSessionState = this.mediaPlayerState.getServerState();
    this.mediaControlServer.updateMediaSessionStates([mSessionState]);
  }

  async handlePlay(_sessionId?: IMediaSessionId): Promise<void> {
    this.mediaPlayerState.playbackStatus = PlaybackStatus.PLAYING;
    this.mediaPlayerState.playbackSpeed = 1.0;
    const mSessionState: MediaSessionState = {
      ...this.mediaPlayerState.getServerState(),
    };

    if (mSessionState === undefined) {
      throw new Error('MediaSessionStateが定義されていません');
    }

    this.mediaControlServer.updateMediaSessionStates([mSessionState]);
    return Promise.resolve();
  }

  async handlePause(_sessionId?: IMediaSessionId): Promise<void> {
    this.mediaPlayerState.playbackStatus = PlaybackStatus.PAUSED;
    this.setMediaSessionState();
    return Promise.resolve();
  }

  async handleGetSessionState(
    _sessionId?: IMediaSessionId,
  ): Promise<MediaSessionState[]> {
    const mSessionState = this.mediaPlayerState.getServerState();
    if (mSessionState === undefined) {
      throw new Error('セッション状態を取得できません');
    }
    return Promise.resolve([mSessionState]);
  }

  async handleGetMetadataInfo(id: MediaId): Promise<IMediaMetadata> {
    return Promise.resolve({
      mediaId: id.contentId,
      title: 'サンプルタイトル',
      date: '2024-01-01',
      artwork: [
        {
          url: 'https://example.com/artwork1.jpg',
          sizeTag: 'medium',
          id: 'sample artwork id1',
          tag: 'fantastic',
        },
        {
          url: 'https://example.com/artwork2.jpg',
          sizeTag: 'large',
          id: 'sample artwork id2',
          tag: 'wonderful',
        },
      ],
    });
  }
}

対話型アプリケーションでは、useComponentInstanceメソッドを使ってIComponentInstanceのインスタンスを取得し、次にReact NativeのuseEffectフックの処理の中でMediaControlHandlerAsyncのインスタンスを作成できます。このアプローチを実装する方法は次のとおりです。

  1. UseComponentInstanceメソッドを使用してIComponentInstanceのインスタンスを取得します。
  2. 次に、ReactコンポーネントでuseEffectフックを使用してMediaControlHandlerAsyncインスタンスを作成し、このインスタンスをコンストラクターのパラメーターとして渡します。このように準備しておくことで、コンポーネントがマウントされてcomponentInstanceが使用可能になったらすぐに、MediaControlHandlerAsyncオブジェクトが適切なIComponentInstanceオブジェクトで初期化されるようになります。

このアプローチにより、プロバイダーアプリが初期化されてグラフィカルユーザーインターフェイスがセットアップされるとすぐに、メディアコントロール再生コマンドを処理できるようになります。そのため、メディアコントロール機能がコンポーネントのライフサイクルと必要なIComponentInstanceオブジェクトの可用性に密接に結び付くようになります。

クリップボードにコピーしました。

import { useComponentInstance , IComponentInstance } from '@amazon-devices/react-native-kepler';

export const App = () => {
  const componentInstance: IComponentInstance = useComponentInstance();

  useEffect(() => {
    const mediaControlHandler: IMediaControlHandlerAsync =
      new MediaControlHandlerAsync(componentInstance);
  }, []);

  // ここでは、プロバイダーアプリのユーザーインターフェイスを作成しています
};

メディアコントロールのクライアントアプリの場合

VegaメディアコントロールAPIのクライアントメソッドは、メディアのエコシステムにおいて重要な役割を果たします。主な役割は、再生、一時停止、その他のサポートされている操作などのさまざまなコマンドの、メディアプロバイダーアプリへの送信を簡単に行うことです。クライアントメソッドを使用すると、単一のインターフェイスで一元的に複数のメディアソースを制御できるメディアハブソリューションなど、多様なアプリを柔軟に作成できます。また、テスト目的で使用して、メディアプロバイダーアプリがhandlePlayhandlePauseなどのコマンドおよび関連する引数を正しく受信して処理するかどうかを検証することもできます。このテスト機能を使用することで、メディアプロバイダーアプリがユーザー入力に適切に応答するようにでき、迅速に応答するシームレスなメディア再生体験を維持できるようになります。クライアントメソッドを活用することで、Vegaエコシステム内のメディアアプリの相互運用性と信頼性を高め、ひいてはより統合されたユーザーフレンドリーなメディア使用体験を実現できます。

Vegaメディアコントロールクライアント APIを使用するには、MediaAppLocatorというヘルパークラスをシングルトンクラスとして作成します。このクラスを使用して、MediaControlComponentAsync.MakeMediaControlEndpointLocator()を呼び出してメディアアプリロケーターのインスタンスを取得します。これにより、IMediaControlEndpointLocatorAsyncインターフェイスを実装するオブジェクトが返されます。VegaメディアコントロールAPIを使用していて、かつデバイスにインストールされているメディアプロバイダーアプリを取得するには、このインスタンスを使用します。エンドポイントロケーターインターフェイスは、メディアコントロールプロバイダーアプリのランキングリストを取得するうえで重要な役割を果たします。ランキングは、アプリのフォーカスによって変わります。通常、ランキングリストの最初のアプリは、現在表示されていてアクティブなフォーカスがあるアプリです。重要なのは、エンドポイントがTypeScriptのPromiseベースのメソッドを使用して非同期でフェッチされることです。取得プロセス中にメインスレッドがブロックされることはなく、アプリの応答性が維持されます。

VegaメディアコントロールAPIのクライアントメソッドには、APIの機能と応答性を強化する追加機能があります。クライアントアプリはaddChangeListenerメソッドを呼び出すことで、デバイスで利用可能なメディアエンドポイントの変更を監視するリスナーを登録できます。このリスニング機能は特に、メディアアプリのリストをほぼリアルタイムで最新状態に維持するために役立ちます。デバイスのメディアエンドポイントの状態が変わるのは、新しいメディアアプリをインストールしたり既存のメディアアプリをアンインストールしたりした場合です。このリスナーを実装することで、クライアントアプリはそうした変更を自動的に検出できるようになり、手動でポーリングしたり更新したりする必要がありません。これにより、クライアントアプリには、利用可能なメディアアプリに関する最新情報が常に保持されます。リスナーは、変更が発生したときに適切なアクションをトリガーするように設定できます。変更としては、ユーザーインターフェイスの更新、利用可能なメディアコントロールのリストの更新、利用可能なメディアエンドポイントの新しい組み合わせに応じたアプリ動作の調整などがあります。このリアルタイムの応答性により、クライアントアプリとデバイスのメディアエコシステムの同期が維持され、ユーザーエクスペリエンスが大幅に向上します。

クリップボードにコピーしました。

import {
  VegaMediaControlsError as KMCError,
  IMediaControlClientAsync,
  IMediaControlEndpointLocatorAsync,
  MediaControlComponentAsync,
  MediaSessionState,
  IMediaMetadata,
} from '@amazon-devices/kepler-media-controls';

import {MediaId} from '@amazon-devices/kepler-media-types';

export class MediaAppLocator {
  private static instance: MediaAppLocator = new MediaAppLocator();
  private mediaAppLocator: IMediaControlEndpointLocatorAsync;
  private mediaAppList: IMediaControlClientAsync[];

  private constructor() {
    this.mediaAppLocator = MediaControlComponentAsync.makeMediaControlEndpointLocator();
    this.mediaAppList = [];
  }

  public static getInstance() {
    return this.instance;
  }

  private setMediaAppList = (controllers: IMediaControlClientAsync[]) => {
    // これらのリソースは手動で解放する必要があります
    this.mediaAppList.forEach((client) => client.destroy());
    this.mediaAppList = controllers;
  }

  public addRegistrarListener(onServerListChanged: IMediaControlEndpointLocatorListener) : Promise<ISubscription> {
    return this.mediaAppLocator.addChangeListener(onServerListChanged);
  }

  public getMediaApp(index: number): IMediaControlClientAsync | undefined {
    if (index >= 0 && index < this.mediaAppList.length) {
      return this.mediaAppList[index];;
    } else {
      console.error('getMediaApp invoked with invalid index: ' + index);
      return undefined;
    }
  }

  public fetchMediaApps(): Promise<IMediaControlClientAsync[]> {
    return this.mediaAppLocator
      .getMediaControlEndpoints()
      .then((controllers) => {
        this.setMediaAppList(controllers);
        return controllers;
      })
      .catch((error: KMCError) => {
        console.error('メディアアプリの取得中にエラーが発生しました:' + error.message);
        return [];
      });
  }

  public fetchMediaAppMetadata(index: number, mediaId: MediaId): Promise<IMediaMetadata> {
    const mediaApp = this.getMediaApp(index);
    if (mediaApp) {
      return mediaApp.getMetadata(mediaId);
    } else {
      return Promise.reject();
    }
  }
}

Vegaメディアコントロールのクライアントメソッドは、エンドポイントをIMediaControlClientAsyncオブジェクトのランクキングリストとして返します。このランキングはアプリのフォーカスに基づいており、リストの最初のエンドポイントは現在アクティブフォーカスがあるアプリを表しています。各IMediaControlClientAsyncオブジェクトを使用することで、特定のメディアアプリを操作できます。これらのオブジェクトにより、クライアントアプリは「play」や「pause」などの制御コマンドを特定のメディアアプリに直接送信できます。

Vegaメディアコントロールのクライアントメソッドは、複数のメディアセッションをサポートします。この機能は、複数のビデオ再生モードやピクチャインピクチャモードなどの高度な機能に対応するように設計されています。この機能を使用するには、すべてのクライアントメソッドでオプションのセッションIDパラメータを受け入れます。このメソッドを使用する場合にセッションIDを省略すると、プロバイダーアプリは、アクションをデフォルトセッションで実行します。これに対し、セッションIDを指定した場合は、その特定のセッションに対してアクションが実行されます。この柔軟性により、1つのアプリ内で複数の同時メディアセッションを正確に制御できます。

クリップボードにコピーしました。

let appLocator = MediaAppLocator.getInstance();
// 現在フォーカスのあるアプリのデフォルトセッションにplayコマンドを送信します
let focusedMediaApp = appLocator.getMediaApp(0);
focusedMediaApp?.play().then(() => {
    console.info("play action succeeded");
}).catch((error: Error) => {
    console.error("playアクションが失敗しました。エラー:" + error.message);
});

// 現在フォーカスのあるアプリの識別子2のセッションにpauseコマンドを送信します
let sessionId: IMediaSessionId = { id: 2};

focusedMediaApp?.pause(sessionId).then(() => {
    console.info("pause action succeeded");
}).catch((error: Error) => {
    console.error("pauseアクションが失敗しました。エラー:" + error.message);
});

VegaメディアコントロールAPIは、利用可能なメディアプロバイダーアプリの変更を監視できるようにします。この機能を実装するには、IGetMediaControlEndpointsResponseListenerインターフェイスを使用します。この機能を使用するには、IMediaControlEndpointLocatorListenerインターフェイスを実装するクラスまたは構造体を作成する必要があります。このリスナーは、新しいプロバイダーアプリがインストールされたり既存のプロバイダーアプリがアンインストールされたりするなどの変更がメディアプロバイダーアプリ一覧内で発生するたびに、自動的に呼び出されます。コールバックは、トリガーされたときに、発生した具体的な変更に関する情報を提供するだけではなく、更新されたプロバイダーアプリ一覧全体を送信します。このアプローチにより、クライアントアプリは常にメディアプロバイダーの完全な最新状況を把握できます。完全な最新リストを受け取ることで、アプリの状態を現在のデバイス構成と同期させることができるため、個々の変更を追跡する必要がなくなり、メディアコントロールのエコシステムにおける不整合のリスクが減少します。

クリップボードにコピーしました。

struct MediaControlEndpointLocatorListener
    : ApmfBase<MediaControlEndpointLocatorListener, IMediaControlEndpointLocatorListener> {
    using OnUpdatedEndpointsCallback =
        std::function<void(ArrayView<Ptr<IMediaControlClientAsync> const>)>;
    MediaControlEndpointLocatorListener(OnUpdatedEndpointsCallback cb)
        : onUpdatedEndpointsCallback{cb}
    {
    }
    void onSubscribed(View<ISubscription> const subscription)
    {
        // addListenerがサブスクライブされました
    }

    void onSubscriptionError(View<IError> error)
    {
        // addListenerが失敗しました
    }

    void onEndpointsChanged(ArrayView<Ptr<IMediaControlClientAsync> const> updatedEndpoints)
    {
        onUpdatedEndpointsCallback(updatedEndpoints);
    }

    OnUpdatedEndpointsCallback onUpdatedEndpointsCallback;
};

Ptr<IMediaControlEndpointLocatorListener> listener = Ptr<MediaControlEndpointLocatorListener>::Make(
    [this](ArrayView<Ptr<IMediaControlClientAsync> const> endpoints) {
        // 変更が検出されました
        discoveredEndpoints = endpoints;
    });

endpointLocator->addChangeListener(listener);

VegaメディアコントロールのクライアントAPIには、クライアントアプリが特定のメディアアプリエンドポイントの状態変化を監視できるようにする強力な追加機能がaddListenerメソッドによって実現されています。この状態オブジェクトは、メディアプロバイダーアプリによってupdateMediaSessionStatesメソッドを介してVegaメディアコントロールシステムに伝達されます。この機能は、メディアの再生ステータスやその他の関連するステータス情報をリアルタイムで把握し続けるために不可欠です。この機能を実装するには、指定したメディアアプリの状態が変化するたびに呼び出されるコールバック関数をaddListenerメソッドを使用して登録します。これには、再生ステータスやトラック情報、その他の関連するメディアセッションデータなどの更新が含まれます。addListenerメソッドはISubscriptionのインスタンスを返します。このオブジェクトには、不要になったサブスクリプションをキャンセルするメソッドが用意されています。ISubscriptionオブジェクトに対してキャンセル用メソッドを呼び出すことで、不要なコールバックの実行を防いで、リソースを効率的に管理することができます。

このリスニング機能により、クライアントアプリは、メディアアプリ状態の変化に動的に反応できるようになるので、絶えずポーリングしなくてもよくなります。これにより、最新のメディア再生ステータスをリアルタイムで正確に反映する、応答性の高いユーザーインターフェイスを作成できます。addListenerメソッドをディスプレイの更新、コントロールの調整、他のアプリコンポーネントとの同期で使用すると、アプリをターゲットエンドポイントのメディア再生状態と完全に同期させることができます。

クリップボードにコピーしました。

// このメソッドは、すでに作成済みのMediaAppLocatorクラスに追加できます
public fetchMediaAppState(index: number, sessionId: IMediaSessionId): Promise<MediaSessionState[]> {
    const mediaApp = this.getMediaApp(index);
    if (mediaApp) {
      const sessionStates: Promise<MediaSessionState[]> = mediaApp.getSessionState(sessionId);
      return sessionStates.then((states) => states);
    } else {
      return Promise.reject();
    }
  }

IMediaControlListenerインターフェイスで使用できるaddListenerメソッドによってイベント駆動型の更新を行えるほかにも、getSessionStateメソッドでは最新のメディアセッションオブジェクトをいつでも明示的にリクエストできます。この機能は非同期で動作し、システムの応答性を維持します。特定のメディアセッションIDを使用してこのメソッドを呼び出した場合は、そのセッションのセッション状態情報が返されます。それ以外の呼び出しでは、利用可能なすべてのセッションの情報が返されます。これにより、アプリのニーズに基づいてリクエストを微調整できます。この場合、すべてのアクティブなメディアセッションの大まかな概要が必要か、または特定のメディアセッションの詳細情報が必要かを問いません。この明示的なリクエスト機能とイベント駆動型の更新を組み合わせることで、Vegaメディアコントロールシステムでは、単純なメディアプレーヤーから複雑なメディア管理アプリに至るさまざまなシナリオでメディアコントロールを管理することができます。

クリップボードにコピーしました。

struct GetMediaSessionStateResponseListener
    : ApmfBase<GetMediaSessionStateResponseListener, IGetMediaSessionStateResponseListener> {
    GetMediaSessionStateResponseListener() : future{promise.get_future()} {}
    void onResponse(ArrayView<Ptr<MediaSessionState> const> states)
    {
        // レスポンスを処理します
    }

    void onError(View<IError> error)
    {
        // getMediaSessionStateが失敗しました
    }
};

Ptr<IGetMediaSessionStateResponseListener> listener = Ptr<GetMediaSessionStateResponseListener>::Make();
// すべてのセッションの最新のセッション状態情報を取得します
activeFocusEndpoint->getSessionState(listener, nullptr);

// 識別子1のセッションのセッション状態情報を取得します
Ptr<MediaSessionId> sessionId = MakeBuilder<MediaSessionId>()->id(1)->build().QueryInterface<MediaSessionId>();
activeFocusEndpoint->getSessionState(listener, sessionId);

Vegaメディアコントロールの属性と機能

Vegaメディアコントロールには次の属性を指定できます。

オプション属性

Vegaメディアコントロールのインターフェイスにはオプション属性はありません。

非オプション属性

Vegaメディアコントロールクラスターがリクエストを受け取ることができる属性は次のとおりです。

  • ActiveAudioTrack
  • ActiveMediaId
  • ActiveTextTrack
  • ActiveVideo
  • AvailableActions
  • AvailableAudioTracks
  • AvailableBackwardSkip
  • AvailableForwardSkip
  • AvailableRatings
  • AvailableSpeeds
  • AvailableTextTracks
  • CurrentRating
  • CurrentState
  • CustomControlsState
  • Duration
  • MediaSessionStates
  • PlaybackSpeed
  • RepeatMode
  • SampledPosition
  • SeekRangeEnd
  • SeekRangeStart
  • ShuffleEnabled
  • StartTime

オプションコマンド

Vegaメディアコントロールクラスターがリクエストを受け取るために選択できるコマンドは次のとおりです。

  • 次へ
  • Previous
  • SkipBackward
  • SkipForward
  • StartOver

非オプションコマンド

Vegaメディアコントロールクラスターがリクエストを受け取ることができるコマンドは次のとおりです。

  • ActivateAudioTrack
  • ActivateTextTrack
  • DeactivateTextTrack
  • EnableShuffle
  • FastForward
  • GetMediaSessionState
  • GetMetadata
  • Pause
  • Play
  • 早戻し
  • Seek
  • SendCustomAction
  • SetAudioVolume
  • SetPlaybackSpeed
  • SetRating
  • SetRepeatMode
  • Stop
  • TogglePlayPause

機能

Vegaメディアコントロールには次の機能を指定できます。

  • AdvancedSeek
    • 提供されている属性
      • Duration
      • PlaybackSpeed
      • SampledPosition
      • SeekRangeEnd
      • SeekRangeStart
      • StartTime
    • 提供されているコマンド
      • Seek
  • AudioTracks
    • 提供されている属性
      • ActiveAudioTrack
      • AvailableAudioTracks
    • 提供されているコマンド
      • ActivateAudioTrack
  • TextTracks
    • 提供されている属性
      • ActiveTextTrack
      • AvailableTextTracks
  • VariableSpeed
    • 提供されているコマンド
      • FastForward
      • 早戻し

Vegaメディアコントロールの概要


Last updated: 2025年9月30日