媒体播放器(AVAudioPlayer,MPMoviePlayerViewController)

概要

本章主要接到上次的文章讲音频播放,因为音频播放没有对应的播放视图控件,所以本例子自绘了一个简单的音乐播放界面,包括返回、暂停/播放、进度控制等。

结果展示

(暂停/播放 播放进度拖拉 返回)

流程概要

1.接上次的流程新建一个音乐播放类,模拟MPMoviePlayerViewController的实现;

2.播放音频的时使用IOS内置的类AVAudioPlayer,该类支持播放wav.mp3等格式的音乐,其对应的代理类为AVAudioPlayerDelegate;

3.对于这种初始化赋值代码:self._buttonPlayPause = [[UIButton alloc] init];突然想到这种赋值会存在内存泄露 ,因为分配内存直接赋值给属性变量,变量retain两次最后却只release一次。所以以前的好多代码都有问题。汗!!!

4.NSNotificationCenter添加监视时注意object不要为空而要设为nil,不能会导致难发现的内存奔溃问题。

主要代码

h文件

//
//  MusicPlayerViewController.h
//  MediaPlayer
//
//  Created by God Lin on 14/12/15.
//  Copyright (c) 2014年 arbboter. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

@interface MusicPlayerViewController : UIViewController <AVAudioPlayerDelegate>
{
    AVAudioPlayer* _audioPlayer;
    UIButton* _buttonPlayPause;
    UIButton* _buttonReturn;
    UIImage* _imagePause;
    UIImage* _imagePlay;
    UIImage* _imageReturn;
    UISlider* _sliderPlayer;
    NSURL* _urlMusic;
    NSTimer* _timerPlayProcess;
    BOOL _bPlay;

    UITextView* _textViewInfo;
    NSString* _titleMusic;
}

@property (nonatomic, retain) AVAudioPlayer* _audioPlayer;
@property (nonatomic, retain) UIButton* _buttonPlayPause;
@property (nonatomic, retain) UIButton* _buttonReturn;
@property (nonatomic, retain) UISlider* _sliderPlayer;
@property (nonatomic, retain) NSURL* _urlMusic;
@property (nonatomic, retain) UIImage* _imagePause;
@property (nonatomic, retain) UIImage* _imagePlay;
@property (nonatomic, retain) UIImage* _imageReturn;
@property (nonatomic, readwrite) BOOL _bPlay;
@property (nonatomic, retain) NSTimer* _timerPlayProcess;
@property (nonatomic, retain) UITextView* _textViewInfo;
@property (nonatomic, retain) NSString* _titleMusic;

-(id)initWithContentURL:(NSURL*)url;
-(void)setContentURL:(NSURL*)url;

@end

void AudioFinishedCallBack(SystemSoundID idSound, void* data);

m文件

//
//  MusicPlayerViewController.m
//  MediaPlayer
//
//  Created by God Lin on 14/12/15.
//  Copyright (c) 2014年 arbboter. All rights reserved.
//

#import "MusicPlayerViewController.h"

@interface MusicPlayerViewController ()

@end

@implementation MusicPlayerViewController
@synthesize _audioPlayer, _urlMusic;
@synthesize _buttonPlayPause, _buttonReturn;
@synthesize _sliderPlayer, _titleMusic;
@synthesize _imagePause, _imageReturn, _imagePlay;
@synthesize _bPlay, _timerPlayProcess, _textViewInfo;

// 布局
-(void) doRotateAction:(NSNotification *) notification
{
    [self relayout];
}
-(void)relayout
{
    CGFloat x = self.view.frame.origin.x;
    CGFloat y = self.view.frame.origin.y + 20;
    CGFloat w = self.view.frame.size.width;
    CGFloat h = self.view.frame.size.height - 20;

    CGFloat x1 = 0;
    CGFloat y1 = 0;
    CGFloat w1 = 0;
    CGFloat h1 = 0;
    UIImage* image = self._imagePause;

    if(w < h)
    {
        image = [UIImage imageNamed:@"oca.jpeg"];
    }
    else
    {
        image = [UIImage imageNamed:@"flower.jpg"];
    }
    self.view.backgroundColor = [UIColor colorWithPatternImage:image];

    image = self._imageReturn;
    x1 = x + 5;
    y1 = y + 5;
    w1 = image.size.width;
    h1 = image.size.height;
    self._buttonReturn.frame = CGRectMake(x1, y1, w1, h1);

    image = self._imagePause;
    x1 = x + 5;
    y1 = (y + h) - (image.size.height + 5);
    w1 = image.size.width;
    h1 = image.size.height;
    self._buttonPlayPause.frame = CGRectMake(x1, y1, w1, h1);

    x1 += image.size.width ;
    w1 = x + w - 5 - x1;
    self._sliderPlayer.frame = CGRectMake(x1, y1, w1, h1);

    x1 = x + 5;
    y1 = y + h/4;
    w1 = w - 10;
    h1 = h/2;
    NSArray* fontArray = [UIFont familyNames];
    NSString* fontName = [fontArray objectAtIndex:arc4random()%[fontArray count]];
    _textViewInfo.font = [UIFont fontWithName:fontName size:h1/10];
    _textViewInfo.frame = CGRectMake(x1, y1, w1, h1);
    _textViewInfo.editable = NO;
    _textViewInfo.textAlignment = NSTextAlignmentCenter;
    _textViewInfo.backgroundColor = [UIColor clearColor];
}
// 播放界面控件
-(void)onDragPlayProcess
{
    [self._audioPlayer setCurrentTime:self._sliderPlayer.value];
}
-(void)onPlayProcess
{
    self._sliderPlayer.value = self._audioPlayer.currentTime;

    NSInteger nTime = _sliderPlayer.value;
    NSInteger nMaxTime = _sliderPlayer.maximumValue;
    NSString* info = [[NSString alloc] initWithFormat:@"%@\n%02ld:%02ld - %02ld:%02ld", _titleMusic, nTime/60, nTime%60, nMaxTime/60, nMaxTime%60];
    _textViewInfo.text = info;
    [info release];
}

// 设置播放的文件
-(id)initWithContentURL:(NSURL*)url
{
    self = [super init];
    if(self)
    {
        [self setContentURL:url];
    }
    return self;
}
-(void)setContentURL:(NSURL*)url
{
    self._urlMusic = url;
}

// 启动播放,画面出现前
-(void)viewWillAppear:(BOOL)animated
{
    [self onPlay];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self._imagePlay = [UIImage imageNamed:@"play.png"];
    self._imagePause = [UIImage imageNamed:@"pause.png"];
    self._imageReturn = [UIImage imageNamed:@"return.png"];

    // 突然想到这种赋值会存在内存泄露 -> 分配内存直接赋值给属性变量
    // 因为retain两次最后却只release一次,所以以前的好多都有问题
    // 汗!!!
    UIButton* button = nil;
    button = [[UIButton alloc] init];
    self._buttonPlayPause = button;
    [button release];
    [self.view addSubview:self._buttonPlayPause];
    [self._buttonPlayPause setImage:self._imagePause forState:UIControlStateNormal];
    [self._buttonPlayPause addTarget:self action:@selector(onPlayPause) forControlEvents:UIControlEventTouchUpInside];

    button = [[UIButton alloc] init];
     self._buttonReturn = button;
    [button release];
    [self.view addSubview:self._buttonReturn];
    [self._buttonReturn setImage:self._imageReturn forState:UIControlStateNormal];
    [self._buttonReturn addTarget:self action:@selector(onStop) forControlEvents:UIControlEventTouchUpInside];

    UISlider* slider = [[UISlider alloc] init];
    self._sliderPlayer = slider;
    [slider release];
    [self.view addSubview:self._sliderPlayer];
    [self._sliderPlayer addTarget:self action:@selector(onDragPlayProcess) forControlEvents:UIControlEventValueChanged];

    UITextView* textView = [[UITextView alloc] init];
    self._textViewInfo = textView;
    [textView release];
    [self.view addSubview:_textViewInfo];

    [self relayout];

    // 切屏
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(doRotateAction:)
                                                 name:UIDeviceOrientationDidChangeNotification
                                               object:self];
}

-(void)onPlay
{
    if(!_bPlay)
    {
        NSError* error;
        self._bPlay = YES;
        AVAudioPlayer* player = [[AVAudioPlayer alloc] initWithContentsOfURL:self._urlMusic error:&error];
        self._audioPlayer = player;
        [player release];
        self._audioPlayer.delegate = self;

        self._timerPlayProcess = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(onPlayProcess) userInfo:nil repeats:YES];

        //self._audioPlayer;
        self._sliderPlayer.maximumValue = 0.0f;
        // 设置播放时长
        self._sliderPlayer.maximumValue = self._audioPlayer.duration;
        [self._audioPlayer play];

        // 非法音频
        if(_sliderPlayer.maximumValue == 0)
        {
            [self onStop];
        }

        [self onPlayProcess];
    }
}
-(void)onStop
{
    [self dismissViewControllerAnimated:YES completion:nil];
    [self._audioPlayer stop];
    [self._timerPlayProcess invalidate];
    _bPlay = NO;
}

-(void)onPlayPause
{
    UIImage* image = nil;
    _bPlay = !_bPlay;
    if(_bPlay)
    {
        image = self._imagePause;
        [self._audioPlayer play];
    }
    else
    {
        image = self._imagePlay;
        [self._audioPlayer pause];
    }
    [self._buttonPlayPause setImage:image forState:UIControlStateNormal];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)dealloc
{
    [_buttonReturn release];
    [_buttonPlayPause release];
    [_imageReturn release];
    [_imagePause release];
    [_imagePlay release];
    [_audioPlayer release];
    [_urlMusic release];
    [_sliderPlayer release];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}
#pragma mark - AVAudioPlayerDelegate
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
    NSLog(@"Music play over");
    [self onStop];
}

/* if an error occurs while decoding it will be reported to the delegate. */
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error
{
    NSLog(@"Music play occured error");
    [self onStop];
}
@end

// 音频播放回调函数
void AudioFinishedCallBack(SystemSoundID idSound, void* data)
{
    AudioServicesDisposeSystemSoundID(idSound);
}

项目工程

时间: 2024-10-11 09:03:24

媒体播放器(AVAudioPlayer,MPMoviePlayerViewController)的相关文章

c#开发的媒体播放器

在Microsoft Visual C# .NET 中使用 DirectShow 控件,来开发一个媒体播放器.按照本文介绍的操作步骤,您可以创建一个简单 Visual C# 应用程序,用来播放数字音频和视频. 介绍 Microsoft Visual C# 是世界上最流行的编程语言,利用 Visual C# 的最新版本 Visual C# .NET,您能够快速.有效地开发基于 Windows 窗体的应用程序,还可以为嵌入了 Microsoft Windows Media? Player 9 Ser

QtQuick2实现媒体播放器(界面)

这里提供一个QtQuick2实现媒体播放器(界面).供大家学习的啦~ 先看效果图:播放器启动后的界面,部分图标来自互联网. 打开媒体文件 播放文件 快捷键控制Ctrl+H: 隐藏/显示 播放栏 当鼠标悬停在一些按钮上时可以显示提示. 关于 源代码包&程序点这里下载

【转】媒体播放器三大底层架构

媒体播放工具,这里主要指视频播放,因为要面临庞大的兼容性和纷繁复杂的算法,从架构上看,能脱颖而出的体系屈指可数.大体来说业界主要有3大架构:MPC.MPlayer和VLC.这3大架构及其衍生品占领了90%的市场,凡是用户能看到的免费媒体播放软件,无一不是源自这3大架构. MPC-HC架构  MPC(Media Player Classic)和它的后续者MPC-HC应该并列而说.MPC基于DirectShow架构,是Windows系统下元祖级别的播放器.包括KMP之流 最早也就是抄来MPC的代码再

简单媒体播放器

// //  ViewController.m //  简单媒体播放器 // //  Created by 殷婷婷 on 15-6-12. //  Copyright (c) 2015年 lanou. All rights reserved. // #import "ViewController.h" #import <MediaPlayer/MediaPlayer.h> @interface ViewController () @property(nonatomic,st

媒体播放器三大底层架构

自射手影音推出以来,生活中越来越多的时间开始被代码和各种Bug-Fix淹没.埋头在田里太久,常常会在一时之间忘记身处何方.所以偶尔上来透透气,顺便将一些经验和心得与大家分享. 媒体播放工具,这里主要指视频播放,因为要面临庞大的兼容性和纷繁复杂的算法,从架构上看,能脱颖而出的体系屈指可数.大体来说业界主要有3大架构:MPC.MPlayer和VLC.这3大架构及其衍生品占领了90%的市场,凡是用户能看到的免费媒体播放软件,无一不是源自这3大架构. MPC/HC架构 MPC(Media Player

JavaScript自定义媒体播放器

使用<audio>和<video>元素的play()和pause()方法,可以手工控制媒体文件的播放.组合使用属性.事件和这两个方法,很容易创建一个自定义的媒体播放器,如下面的例子所示. 1 <div class="mediaplayer"> 2 <div class="video"> 3 <video id="player" src="movie.mov" poster=

转:媒体播放器三大底层架构

媒体播放工具,这里主要指视频播放,因为要面临庞大的兼容性和纷繁复杂的算法,从架构上看,能脱颖而出的体系屈指可数.大体来说业界主要有3大架 构:MPC.MPlayer和VLC.这3大架构及其衍生品占领了90%的市场,凡是用户能看到的免费媒体播放软件,无一不是源自这3大架构.? ? MPC-HC架构? MPC(Media Player Classic)和它的后续者MPC-HC应该并列而说.MPC基于DirectShow架构,是Windows系统下元祖级别的播放器.包括KMP之流 最早也就是抄来MPC

(原创)jQuery Media Plugin-jQuery的网页媒体播放器插件的使用心得

jQuery Media Plugin是一款基于jQuery的网页媒体播放器插件,它支持大部分的网络多媒体播放器和多媒体格式,比如:Flash, Windows Media Player, Real Player, Quicktime, MP3,Silverlight, PDF.它根据当前的脚本配置,自动将a标签替换成div,并生成object, embed甚至是iframe代码,至于生成object还是embed,jQuery Media会根据当前平台自动判别,因此兼容性方面非常出色下面这段代

C#编写媒体播放器--Microsoft的Directx提供的DirectShow组件,该组件的程序集QuartzTypeLib.dll.

使用C#编写媒体播放器时,需要用到Microsoft的Directx提供的DirectShow组件.用该组件前需要先注册程序集QuartzTypeLib.dll. 1.用QuartzTypeLib.dll播放视频 1.1Form1.cs using System; using System.Windows.Forms; using QuartzTypeLib; namespace DirectShow {     public partial class Form1 : Form     {