# -*- encoding: UTF-8 -*-
require 'csd/application/minisip/phonebook_example'
module CSD
module Application
module Minisip
# This namespace is reserved for sub-components of this application. This is done for better readability and modularity
# (i.e. less risky to fail in production).
#
module Component
# This MiniSIP component is the very minisip source code itself.
#
module Core
# This is an +Array+ containing the names of the internal MiniSIP libraries. Note that they
# are sorted according to the sequence in which they need to be compiled (because they depend on each other).
#
LIBRARIES = %w{ libmutil libmnetutil libmcrypto libmikey libmsip libmstun libminisip minisip }
class << self
# This method processes the MiniSIP Core component and does everything needed for compiling it. Note that
# it is not responsible for checking depenencies here. It will just focus on compiling the internal MiniSIP libraries.
#
def compile
UI.debug "#{self}.compile was called"
UI.debug "The current Options are: #{CSD.options.inspect}"
remove_ffmpeg
if Path.repository.directory? and !Options.reveal
UI.warn "The MiniSIP source code will not be downloaded, because the directory #{Path.repository.enquote} already exists."
else
checkout
modify_source_code
end
modify_dirlist
compile_libraries # We would like to re-compile MiniSIP no matter what options were given as command-line arguments.
link_libraries
create_address_book
end
def remove_ffmpeg
ffmpeg_available = Cmd.run('ffmpeg -h', :internal => true, :die_on_failure => false).success?
return if Options.ffmpeg_first or !Options.configure or !libraries.include?('libminisip') or !ffmpeg_available
UI.debug "MILESTONE: removing_ffmpeg"
if Gem::Platform.local.debian?
# Note that FFmpeg must have been installed via apt-get or via the AI in order for this to work,
# because manual compilations of FFmpeg cannot be removed automatically
UI.info "Removing FFmpeg before re-compiling MiniSIP".green.bold
UI.info "You can skip this step by giving the option --force-ffmpeg".yellow
Cmd.run "sudo apt-get remove ffmpeg --yes", :announce_pwd => false
else
# On other linux distributions we don't know how to remove ffmpeg
UI.debug "MILESTONE: cannot_remove_ffmpeg"
raise Error::Minisip::Core::FFmpegInstalled, "Please remove ffmpeg from your system first, or run the #{CSD.executable} with --no-configure" unless Options.testmode
end
end
# This method provides upfront information to the user about how the MiniSIP Core component will be processed.
#
def introduction
UI.info " MiniSIP".green.bold
# If the repository directory already exists, we indicate that here
download_text = Path.repository.directory? ? " - located at: " : " - downloading to: "
UI.info download_text.green + Path.repository.to_s.yellow
# Now let's present which libraries will be compiled with which commands
UI.info " - libraries to process: ".green + libraries.join(', ').yellow
UI.info " - with these commands: ".green + [('bootstrap' if Options.bootstrap), ('configure' if Options.configure), ('make' if Options.make), ('make install' if Options.make_install)].compact.join(', ').yellow
end
# Determines which libraries of MiniSIP should be processed, because the --only parameter might be set
# by the user, requesting for only a subset of the libraries.
#
def libraries
Options.only ? LIBRARIES.map { |lib| lib if Options.only.to_a.include?(lib) }.compact : LIBRARIES
end
# This method downloads the minisip source code in the right version. If the Options.branch
# parameter is set to a branchname of the source code repository, that branch will be downloaded. Currently
# this function uses the intermediary Github repository to make sure that
# * the downloaded version is not a risky cutting-edge trunk
# * the download works even if the vendor's repository is down (again)
# That means that the Github repository (or any other intermediary repository) should be manually updated
# by an TTA AI developer, after having made sure that that source code version is working properly.
#
def checkout
Cmd.git_clone 'MiniSIP repository', 'http://github.com/csd/minisip.git', Path.repository
if Options.branch
Cmd.cd Path.repository, :internal => true
Cmd.run "git pull origin #{Options.branch}"
end
end
# Some places in the MiniSIP source code have to be modified before it can be compiled.
# In this case, an absolute path must be replaced with the current absolute prefix path.
# Furthermore, modifications of some constants will be done, because this is more compatible
# with the most recent FFmpeg version. In fact, MiniSIP won't compile if FFmpeg is present
# and this has not been modified.
# See http://www.howgeek.com/2010/03/01/ffmpeg-php-error-‘pix_fmt_rgba32’-undeclared-first-use-in-this-function
# and http://ffmpeg.org/doxygen/0.5/pixfmt_8h.html#33d341c4f443d24492a95fb7641d0986 for more information.
#
def modify_source_code
UI.info "Fixing MiniSIP OpenGL GUI source code".green.bold
Cmd.replace(Path.repository_open_gl_display, '/home/erik', Path.build)
if Options.ffmpeg_first
UI.info "Fixing MiniSIP Audio/Video en/decoder source code".green.bold
Cmd.replace(Path.repository_avcoder_cxx, 'PIX_FMT_RGBA32', 'PIX_FMT_RGB32')
Cmd.replace(Path.repository_avdecoder_cxx, 'PIX_FMT_RGBA32', 'PIX_FMT_RGB32')
end
end
# Usually, Ubuntu ignores /usr/local/share/aclocal. So we need to create a file called
# +dirlist+ in /usr/share/aclocal which contains the path to the other directory.
#
def modify_dirlist
Path.dirlist = Pathname.new File.join('/', 'usr', 'share', 'aclocal', 'dirlist')
if !Path.dirlist.file? and Gem::Platform.local.debian?
UI.info "Fixing broken Debian aclocal path".green.bold
Path.new_dirlist = Pathname.new File.join(Path.work, 'dirlist')
Cmd.touch_and_replace_content Path.new_dirlist, '/usr/local/share/aclocal'
Cmd.run "sudo mv #{Path.new_dirlist} #{Path.dirlist}", :announce_pwd => false
end
end
def link_libraries
UI.info "Linking shared MiniSIP libraries".green.bold
Cmd.run "sudo ldconfig #{Path.build_lib_libminisip_so}", :announce_pwd => false
end
def libminisip_cpp_flags
if Options.ffmpeg_first
%{CPPFLAGS="-I#{Path.hdviper_x264} -I#{Path.hdviper_x264_test_x264api} -I#{Path.ffmpeg_libavutil} -I#{Path.ffmpeg_libavcodec} -I#{Path.ffmpeg_libswscale} -I#{Path.repository_grabber} -I#{Path.repository_decklinksdk}"}
else
%{CPPFLAGS="-I#{Path.hdviper_x264} -I#{Path.hdviper_x264_test_x264api} -I#{Path.repository_grabber} -I#{Path.repository_decklinksdk}"}
end
end
def libminisip_ld_flags
%{LDFLAGS="#{Path.hdviper_libx264api} #{Path.hdviper_libtidx264} -lpthread -lrt"}
end
# Iteratively processes the internal MiniSIP libraries (+bootstrap+, +configure+, +make+, +make install+).
#
def compile_libraries
create_build_dir
libraries.each do |library|
directory = Pathname.new(File.join(Path.repository, library))
if Cmd.cd(directory, :internal => true).success? or Options.reveal
UI.debug "MILESTONE: processing_#{library}"
UI.info "Processing MiniSIP -> #{library}".green.bold
bootstrap
configure library
make
make_install
else
UI.warn "Skipping MiniSIP library #{library} because it could not be found in #{directory.enquote}"
end
end
end
# Creates all build directories such as +lib+, +share+, +bin+, etc.
#
def create_build_dir
# In sudo mode, we don't need to create these. They already exist in the OS.
return unless Options.this_user
UI.info "Creating target build directories".green.bold
[Path.build, Path.build_include, Path.build_lib, Path.build_share, Path.build_share_aclocal].each { |target| Cmd.mkdir target }
end
# This method runs the `bootstrap´ command in the current directory unless --no-bootstrap was given.
# It is only used for the internal MiniSIP libraries.
#
def bootstrap
bootstrap! if Options.bootstrap
end
# This method forces running the `bootstrap´ command in the current directory.
# It is only used for the internal MiniSIP libraries.
#
def bootstrap!
if Options.this_user
Cmd.run(%Q{./bootstrap -I "#{Path.build_share_aclocal}"})
else
Cmd.run("./bootstrap")
end
end
def configure(name='')
configure! name if Options.configure
end
def configure!(name='')
individual_options = case name
when 'libminisip'
%Q{--enable-debug --enable-video --enable-opengl --disable-mil --enable-decklink --disable-sdl #{libminisip_cpp_flags} #{libminisip_ld_flags}}
when 'minisip'
%Q{--enable-debug --enable-video --enable-opengl --enable-textui}
else
''
end
common_options = Options.this_user ? %Q{--prefix="#{Path.build}" PKG_CONFIG_PATH="#{Path.build_lib_pkg_config}" ACLOCAL_FLAGS="#{Path.build_share_aclocal}" LD_LIBRARY_PATH="#{Path.build_lib}"} : ''
Cmd.run ['./configure', common_options, individual_options].join(' ')
end
def make
make! if Options.make
end
def make!
Cmd.run("make")
end
def make_install
make_install! if Options.make_install
end
def make_install!
if Options.this_user
Cmd.run("make install")
else
Cmd.run("sudo make install")
end
end
# Execute the MiniSIP GTK GUI.
#
def run_gtkgui
UI.info "Executing MiniSIP".green.bold
if Options.this_user
Cmd.run Path.build_gtkgui, :die_on_failure => false, :announce_pwd => false
else
Cmd.run 'minisip_gtkgui', :die_on_failure => false, :announce_pwd => false
end
end
def modify_libminisip_rules
if Path.repository_libminisip_rules_backup.file?
UI.warn "The libminisip rules seem to be fixed already, I won't touch them now. Delete #{Path.repository_libminisip_rules_backup.enquote} to enforce it."
else
Cmd.copy Path.repository_libminisip_rules, Path.repository_libminisip_rules_backup
Cmd.replace Path.repository_libminisip_rules, 'AUTOMATED_INSTALLER_PLACEHOLDER=""', [libminisip_cpp_flags, libminisip_ld_flags].join(' ')
end
end
def create_address_book
return if Path.phonebook.file?
UI.info "Creating default MiniSIP phonebook".green.bold
Cmd.touch_and_replace_content Path.phonebook, ::CSD::Application::Minisip::PHONEBOOK_EXAMPLE, :internal => true
UI.info " Phonebook successfully saved in #{Path.phonebook}".yellow
end
# Iteratively makes debian packages of the internal MiniSIP libraries.
# TODO: Refactor this, it looks terribly sensitive.
# TODO: Check for GPL and LGLP license conflicts.
#
def package!
Cmd.mkdir(Path.packaging)
libraries.each do |library|
directory = Pathname.new(File.join(Path.repository, library))
next if Options.only and !Options.only.include?(library)
UI.info "Making #{library} with target dist".green.bold
if Cmd.cd(directory) or Options.reveal
Cmd.run("make dist")
tar_filename = File.basename(Dir[File.join(directory, '*.tar.gz')].first)
Cmd.move(File.join(directory, tar_filename.to_s), Path.packaging) if tar_filename or Options.reveal
if Cmd.cd(Path.packaging) or Options.reveal
Cmd.run("tar -xzf #{tar_filename}")
tar_dirname = File.basename(tar_filename.to_s, '.tar.gz')
if Cmd.cd(File.join(Path.packaging, tar_dirname))
Cmd.run("dpkg-buildpackage -rfakeroot")
if library == 'minisip'
if Cmd.cd(Path.packaging)
package = File.basename(Dir[File.join(Path.packaging, "#{library}*.deb")].first)
Cmd.run("sudo dpkg -i #{package}") if package or Options.reveal
end
else
if Cmd.cd(Path.packaging)
package = File.basename(Dir[File.join(Path.packaging, "#{library}0*.deb")].first)
Cmd.run("sudo dpkg -i #{package}") if package or Options.reveal
dev_package = File.basename(Dir[File.join(Path.packaging, "#{library}-dev*.deb")].first)
Cmd.run("sudo dpkg -i #{dev_package}") if dev_package or Options.reveal
end
end
else
UI.error "Could not enter #{File.join(Path.packaging, tar_dirname)}."
end
else
UI.error "Could not enter #{Path.packaging}."
end
else
UI.error "Could not enter #{directory}."
end
end
Cmd.cd '/'
Cmd.run('minisip_gtkgui')
end
end
end
end
end
end
end